【问题标题】:python filtering list of dict by dict containing several key-value pairs as conditionspython通过包含几个键值对作为条件的dict过滤dict列表
【发布时间】:2016-07-31 03:29:33
【问题描述】:

我的示例数据:

list_of_dict =[{'cena': 23, 'nazwa': 'item1', 'param': 'pampam'},
               {'cena': 26, 'nazwa': 'item2', 'param': 'iko'   },
               {'cena': 26, 'nazwa': 'item2a','param': 'ik2'   },
               {'cena': 26, 'nazwa': 'item2b','param': 'ik2'   },
               {'cena': 17, 'nazwa': 'item3', 'param': 'etr'   },
               {'cena': 17, 'nazwa': 'item4', 'param': 'asdf'  }]

conditions =   {'cena': 26, 'param': 'ik2' }

我试过了:

if conditions in list_of_dict:
    do_something()

它有效,但只有当整个条件 dict(每个键)与 dict 列表中的一个匹配时,我的意思是:

In [1]: exampleSet =      [{  'type' : 'type1', 'k' : 'kval'},
   ...:                    {  'type' : 'type2', 'k' : 'kv2' },
   ...:                    {  'type' : 'type2', 'k' : 'k3'  },
   ...:                    {  'type' : 'type3', 'k' : 'k3'  }]
   ...: 
   ...: conditions =       {  'type' : 'type1', 'k' : 'kval' }
   ...: 
   ...: 
   ...: conditions in exampleSet
   ...: 
Out[1]: True
In [2]: conditions =       {  'type' : 'type1' }

In [3]: conditions in exampleSet
Out[3]: False

当我尝试将字典与指定的键值对匹配时,(无论值/是否存在未指定的值)所以

In [4]: exampleSet =      [{  'type' : 'type1', 'k' : 'kval'},
   ...:                    {  'type' : 'type2', 'k' : 'kv2' },
   ...:                    {  'type' : 'type2', 'k' : 'k3'  },
   ...:                    {  'type' : 'type3', 'k' : 'k3'  }]
   ...: 
   ...: conditions =       {  'type' : 'type2' }
   ...:
   ...: my_wanted_match( exampleSet, conditions )

必须返回:

                     [{  'type' : 'type2', 'k' : 'kv2' },
                      {  'type' : 'type2', 'k' : 'k3'  }]

结果。

谁能给我一些关于如何实现这一点的提示?

【问题讨论】:

标签: python list dictionary filter matching


【解决方案1】:

这是您想要的filter() - 您想根据某些条件过滤您的字典列表;只返回符合所有条件的条目。

>>> list_of_dict =[{'cena': 23, 'nazwa': 'item1', 'param': 'pampam'},
...                {'cena': 26, 'nazwa': 'item2', 'param': 'iko'   },
...                {'cena': 26, 'nazwa': 'item2a','param': 'ik2'   },
...                {'cena': 26, 'nazwa': 'item2b','param': 'ik2'   },
...                {'cena': 17, 'nazwa': 'item3', 'param': 'etr'   },
...                {'cena': 17, 'nazwa': 'item4', 'param': 'asdf'  }]

设置条件:

>>> conditions = {'param':'iko'}

并做一个单行过滤:

>>> filter(lambda item: all((item[k]==v for (k,v) in conditions.iteritems())), list_of_dict)
[{'cena': 26, 'param': 'iko', 'nazwa': 'item2'}]

【讨论】:

    【解决方案2】:

    使用列表理解:

    >>> list_of_dict =[{'cena': 23, 'nazwa': 'item1', 'param': 'pampam'},
    ...                {'cena': 26, 'nazwa': 'item2', 'param': 'iko'   },
    ...                {'cena': 26, 'nazwa': 'item2a','param': 'ik2'   },
    ...                {'cena': 26, 'nazwa': 'item2b','param': 'ik2'   },
    ...                {'cena': 17, 'nazwa': 'item3', 'param': 'etr'   },
    ...                {'cena': 17, 'nazwa': 'item4', 'param': 'asdf'  }]
    >>> 
    >>> conditions =   {'cena': 26, 'param': 'ik2' }
    >>> [d for d in list_of_dict if all((k in d and d[k] == v) for k, v in conditions.items())]
    [{'cena': 26, 'param': 'ik2', 'nazwa': 'item2a'}, {'cena': 26, 'param': 'ik2', 'nazwa': 'item2b'}]
    

    【讨论】:

      【解决方案3】:

      这将遍历list_of_dict 中的每个字典,并将具有匹配键值对的字典返回到每个条件。

      matches = [one_dict for one_dict in list_of_dict if
                 all(key in one_dict and conditions[key] == one_dict[key] 
                     for key in conditions.keys())]
      >>> matches
      [{'cena': 26, 'nazwa': 'item2a', 'param': 'ik2'},
       {'cena': 26, 'nazwa': 'item2b', 'param': 'ik2'}]
      

      【讨论】:

        【解决方案4】:

        sets 在这里派上用场*:

        has_match = any(set(condition.items()) <= set(d.items()) for d in listOfDict)
        

        或者你的第二部分:

        the_matches = [
            d
            for d in listOfDict
            if set(condition.items()) <= set(d.items())
        ]
        

        &lt;= 是应用于集合时的子集运算符:

        issubset(other)
        set &lt;= other

        测试集合中的每个元素是否在其他元素中。

        *只要你能确保你的值是可散列的,即不是列表或字典

        【讨论】:

          【解决方案5】:
          def my_wanted_match(example_set, conditions):
              conditions = conditions.items()
              match = []
              for e in example_set:
                  if all([c in set(e.items()) for c in conditions]):
                      match.append(e)
              return match
          

          或者简单地说:

          match = [e for e in example_set
                   if all([c in set(e.items()) for c in set(conditions.items())])]
          

          【讨论】:

          • set 将抛出,如果 e.values() 中的任何一个不可散列,遗憾的是
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-03
          • 2022-06-17
          • 2020-07-15
          • 2021-11-24
          相关资源
          最近更新 更多