比较两个字典列表中的值的Python方法 我是Python的新手,我还在尝试在Python中摆脱C++编码技术,所以请原谅我这是个小问题。我似乎找不到最适合做这件事的方法

比较两个字典列表中的值的Python方法 我是Python的新手,我还在尝试在Python中摆脱C++编码技术,所以请原谅我这是个小问题。我似乎找不到最适合做这件事的方法,python,list,python-2.7,dictionary,Python,List,Python 2.7,Dictionary,我有两张单子。两个列表中的单个dict可能包含嵌套dict。(如果你好奇的话,这实际上是一些Yelp数据。)第一个DICT列表包含如下条目: {business_id': 'JwUE5GmEO-sH1FuwJgKBlQ', 'categories': ['Restaurants'], 'type': 'business' ...} {'business_id': 'vcNAWiLM4dR7D2nwwJ7nCA', 'date': '2010-03-22', 'review_id':

我有两张单子。两个列表中的单个dict可能包含嵌套dict。(如果你好奇的话,这实际上是一些Yelp数据。)第一个DICT列表包含如下条目:

{business_id': 'JwUE5GmEO-sH1FuwJgKBlQ',
 'categories': ['Restaurants'],
 'type': 'business'
 ...}
{'business_id': 'vcNAWiLM4dR7D2nwwJ7nCA',
 'date': '2010-03-22',
 'review_id': 'RF6UnRTtG7tWMcrO2GEoAg',
 'stars': 2,
 'text': "This is a basic review",
 ...}
第二个DICT列表包含如下条目:

{business_id': 'JwUE5GmEO-sH1FuwJgKBlQ',
 'categories': ['Restaurants'],
 'type': 'business'
 ...}
{'business_id': 'vcNAWiLM4dR7D2nwwJ7nCA',
 'date': '2010-03-22',
 'review_id': 'RF6UnRTtG7tWMcrO2GEoAg',
 'stars': 2,
 'text': "This is a basic review",
 ...}
我想做的是提取第二个列表中与第一个列表中的特定类别匹配的所有条目。例如,如果我对餐馆感兴趣,我只想要第二个列表中的实体,其中
business\u id
与第一个列表中的
business\u id
匹配,并且单词
restaurants
出现在
类别的值列表中

如果我在SQL中将这两个列表作为表,我会在
business\u id
属性上进行连接,然后只需一个简单的过滤器即可获得我想要的行(在
类别中的
餐厅
,或类似的地方)


这两个列表非常大,因此我遇到了效率和内存空间问题。在我将所有这些都放入SQL数据库之前,有人能给我一些提示吗?我曾和一些熊猫混在一起,所以我在这方面的经验有限。我在合并过程中遇到了问题。

假设您的列表名为
l1
l2

l1
中的所有元素:
l1
餐厅
类别的所有元素:
l2
中的所有元素将
id
l1
中的元素与
餐厅
类别匹配:
让我们定义字典的示例列表:

first = [
        {'business_id':100, 'categories':['Restaurants']},
        {'business_id':101, 'categories':['Printer']},
        {'business_id':102, 'categories':['Restaurants']},
        ]

second = [
        {'business_id':100, 'stars':5},
        {'business_id':101, 'stars':4},
        {'business_id':102, 'stars':3},
        ]
我们可以通过两个步骤提取感兴趣的项目。第一步是收集属于餐厅的企业ID列表:

ids = [d['business_id'] for d in first if 'Restaurants' in d['categories']]
第二步是获取与这些ID对应的DICT:

[d for d in second if d['business_id'] in ids]
这导致:

[{'business_id': 100, 'stars': 5}, {'business_id': 102, 'stars': 3}]
你可以做:

餐厅id=[biz['id']如果是biz['categories']中的“餐厅”,则列表1中的biz为[biz['id']
餐厅数据=[rest for rest in list2 if rest['id']in restaurant_id]


然后,
restaurant\u data
将包含列表2中包含餐馆数据的所有词典

这很棘手,我玩得很开心。这就是我要做的:

def match_fields(business, review):
    return business['business_id'] == review['business_id'] and 'Restaurants' in business['categories']

def search_businesses(review):
    # the lambda binds the given review as an argument to match_fields
    return any(lambda business: match_fields(business, review), business_list)

answer = filter(search_businesses, review_list)
这是我发现的最具可读性的方式。我不太喜欢超过一行的列表理解,三行确实在推动它。如果您想让它看起来更简洁,只需使用更短的变量名。为了清晰起见,我喜欢长的


我定义了一个函数,如果一个条目可以在列表之间匹配,它将返回true,第二个函数将帮助我搜索审阅列表。然后我可以说:去掉任何在业务列表中没有匹配条目的评论。此模式适用于列表之间的任意检查

Python程序员喜欢将使用作为完成逻辑和设计的一种方式

列表的理解使表达更加简洁。您将其视为一种查询语言是正确的

x = [comparison(a, b) for (a, b) in zip(A, B)] 
x = [comparison(a, b) for (a, b) in itertools.product(A, B)] 
x = [comparison(a, b) for a in A for b in B if test(a, b)]
x = [comparison(a, b) for (a, b) in X for X in Y if test(a, b, X)]

…都是我使用的模式。

作为列表理解方法的变体,使用
集合和生成器理解可能更有效。如果你的第一份名单规模很大,或者餐馆总数很大,这一点尤其正确

restaurant_ids = set(biz for biz in first if 'Restaurants' in biz['categories'])
restaurant_data = [rest for rest in second if rest['id'] in restaurant_ids]

请注意,暴力列表理解方法是
O(len(first)*len(second))
,但它不使用额外的内存存储,而这种方法是
O(len(first)+len(second))
,并使用
O(餐厅数量)
集合提供额外内存!我真的很喜欢你把清单上的理解分解的方式。这是一件我花了一段时间才完全理解Python的事情。@TheOriginalBMan,很高兴能提供帮助!我也喜欢这个。来自面向对象编程和函数式编程的背景,这肯定很容易理解。谢谢你@TheOriginalBMan,正如您所知,在Python列表理解映射中,可以说这是Python的函数式风格。当然,这是主观的,在某些情况下可能是合理的。@elyase Python中没有一种语言特性在所有情况下都是首选的。在这种情况下,列表理解需要做大量的逻辑工作,并且最终不会像我们在上述答案中看到的那样具有很强的可读性实用胜过纯洁。可读性很重要Zen@jack,同意你的第一点,这就是我为什么写“在某些情况下可能是合理的”。我不同意我的解决方案更具逻辑性,更具可读性,这是主观的,我尊重你的不同看法,但我刚刚向我的GF(非开发人员,文学背景)展示了这两种解决方案,她只是告诉我她不知道你的解决方案做什么,而我的解决方案读作句子。这正是我的看法。@elyase我并不是说你的解决方案比我的解决方案需要更多的逻辑,只是把同样的逻辑放在列表理解中会变得非常狭窄。另外:将代码显示给非开发人员意义不大,因为不管应用程序如何,您实际上只是比较两种语言功能的外观。”filter'和any'是内置的,这是有充分理由的,可以合理地期望其他开发人员知道它们。
restaurant_ids = set(biz for biz in first if 'Restaurants' in biz['categories'])
restaurant_data = [rest for rest in second if rest['id'] in restaurant_ids]