Python - 根据if键值包含另一个列表中的所有项目来过滤词典列表

时间:2017-05-23 02:48:43

标签: python list dictionary

我有一个类似于此的词典列表,但有大约500个项目:

listOfDicts = [{'ID': 1, 'abc': {'123': 'foo'}}, ... {'ID': 7, 'abc': {'123':'foo','456': 'bar'}}]

sampleFilterList = ['123', '456']

我正在尝试过滤listOfDicts以获取所有结果,其中sampleFilterList中的所有值都在键'abc'中

结果应该是一个列表:

[{'ID': 7, 'abc': {'123':'foo','456': 'bar'}}, ...]

我尝试了[i for i in listOfDicts if a for a in sampleFilterList in i['abc']],但我得到了UnboundLocalError: local variable 'a' referenced before assignment

5 个答案:

答案 0 :(得分:2)

您需要在列表推导中 for 关键字之前移动 in 条件测试,并且使用get会更安全,这会返回默认值如果您不确定列表中的所有词典是否都包含关键字abc,则值而不是抛出错误:

listOfDicts = [{'ID': 1, 'abc': {'123': 'foo'}}, {'ID': 7, 'abc': {'123':'foo','456': 'bar'}}]    ​
sampleFilterList = ['123', '456']

[d for d in listOfDicts if all(s in d.get('abc', {}) for s in sampleFilterList)]
# [{'ID': 7, 'abc': {'123': 'foo', '456': 'bar'}}]

或者如果使用@DYZ中的一组,您可以使用issubset

filterSet = set(sampleFilterList)
[d for d in listOfDicts if filterSet.issubset(d.get('abc', {}))]
# [{'ID': 7, 'abc': {'123': 'foo', '456': 'bar'}}]

答案 1 :(得分:2)

首先,将您的第二个列表转换为一组以进行更有效的比较:

sampleFilterSet = set(sampleFilterList)

现在,比较' abc'每个列表项的键到上述集合:

[item for item in listOfDicts if not (sampleFilterSet - item['abc'].keys())]    
#[{'ID': 7, 'abc': {'123': 'foo', '456': 'bar'}}]

这是最快的解决方案。一个更Pythonic(但有点慢)的解决方案是使用filter()

list(filter(lambda item: not (sampleFilterSet - item['abc'].keys()), listOfDicts))
#[{'ID': 7, 'abc': {'123': 'foo', '456': 'bar'}}]

答案 2 :(得分:0)

这是一个具有嵌套列表推导的工作版本。您的问题是a for a in...是列表解析,需要用于构建新列表。

[i for i in listOfDicts if [a for a in sampleFilterList if a in i['abc']] == sampleFilterList]

答案 3 :(得分:0)

<Router>
<div>
  <Switch>
    <Route path="/" component={Home} />
    <Route 
      exact path="/source" render={() => (
        isAuthenticated() ? (
          <Source />
        ) : (
          <Home /> //I want to Redirect to the Home Page with a flash message if user is not logged in
        )
      )} 
    />
    <Route path="/contact" component={ContactUs} />
  </Switch>
</div>
</Router>,
);

或:

for i in zip(listOfDicts):
 a = i[0]['abc']
 print (a)

这是一种优雅的方式,我希望它会有用。

答案 4 :(得分:0)

您可以尝试以下单行:

passed_the_filter = [[dictionary_entry for dictionary_entry in list_of_dicts if filter_test in dictionary_entry['abc']] for filter_test in filter]

它是一个嵌套列表推导,它遍历过滤器和字典列表。它检查过滤器是否是字典条目“abc”值中的键。您的问题是您使用了错误的列表推导语法。

N.B。您可能需要注意,您可能不确定元素是否具有“abc”键!

感谢您阅读本文。