Python过滤字典列表,条件为多个键值对匹配

5

我的示例数据:

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()

它可以工作,但只有当整个条件字典(每个键)与字典列表中的一个匹配时才能运行,我的意思是:

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中模拟findWhere()的行为 - Lukas Graf
6个回答

6

你需要的是一个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'}]

1
这会遍历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'}]

1

set在这里非常方便*

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())
]

<=是集合运算符中的子集运算符:

issubset(other)
set <= other

测试集合中的每个元素是否都在另一个集合中。

* 前提是您可以确保您的值是可哈希的,即不是列表或字典


0
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())])]

如果 e.values() 中有任何一个不可哈希的元素,set 将会抛出异常。很遗憾。 - Eric

-1
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'  }]

>Answers
 --------

res=list(filter(lambda list_of_dict:list_of_dict['cena']== 26 and list_of_dict['param']== 'ik2',list_of_dict))

for i in range(0,len(res)):
    if 'item2b' in res[i].values() :
        print(res[i])

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接