比较两个词典列表中的价值的Pythonic方法

时间:2015-01-22 02:05:28

标签: python list python-2.7 dictionary

我是Python新手,在Python中我仍然试图摆脱C ++编码技术,所以如果这是一个微不足道的问题,请原谅我。我似乎找不到最恐怖的做法。

我有两个dicts列表。两个列表中的各个dicts可能包含嵌套的dicts。 (它实际上是一些Yelp数据,如果你很好奇。)第一个dicts列表包含这样的条目:

{business_id': 'JwUE5GmEO-sH1FuwJgKBlQ',
 'categories': ['Restaurants'],
 'type': 'business'
 ...}

第二个dicts列表包含如下条目:

{'business_id': 'vcNAWiLM4dR7D2nwwJ7nCA',
 'date': '2010-03-22',
 'review_id': 'RF6UnRTtG7tWMcrO2GEoAg',
 'stars': 2,
 'text': "This is a basic review",
 ...}

我想要做的是提取第二个列表中与第一个列表中的特定类别匹配的所有条目。例如,如果我对餐馆感兴趣,我只希望第二个列表中的business_id与第一个列表中的business_id匹配,而Restaurants字符出现在categories的值列表。

如果我在SQL中将这两个列表作为表格,我会在business_id属性上进行连接,然后只需一个简单的过滤器来获取我想要的行(Restaurants IN { {1}},或类似的东西)。

这两个列表非常大,因此我遇到了效率和内存空间问题。在我将所有这些内容推送到SQL数据库之前,有人能给我一些指示吗?我和Pandas搞砸了一些,所以我对此有一些有限的经验。我在合并过程中遇到了麻烦。

6 个答案:

答案 0 :(得分:2)

假设您的列表名为l1l2

l1的所有元素:

[each for each in l1]

来自l1的{​​{1}}类别的所有元素:

Restaurant

[each for each in l1 if 'Restaurants' in each['categories']] 匹配l2的所有元素与idl1类别的元素:

Restaurant

答案 1 :(得分:2)

让我们定义词典的示例列表:

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相对应的词组:

[d for d in second if d['business_id'] in ids]

这导致:

[{'business_id': 100, 'stars': 5}, {'business_id': 102, 'stars': 3}]

答案 2 :(得分:1)

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

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,另一个函数可以帮助我搜索整个评论列表。然后我可以说:摆脱任何在商家列表中没有匹配条目的评论。此模式适用于列表之间的任意检查。

答案 3 :(得分:1)

Python程序员喜欢使用list comprehensions来实现逻辑和设计。

列表理解导致更紧凑和更紧凑的表达。你认为它非常像查询语言。

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

...是我使用的所有模式。

答案 4 :(得分:1)

由于列表理解的变化仅接近,使用set和生成器理解可能更有效。如果您的第一个列表的大小非常大或者餐馆的总数非常大,则尤其如此。

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(number_of_restaurants)使用set额外内存。

答案 5 :(得分:0)

你可以这样做: restaurant_ids = [biz['id'] for biz in list1 if 'Restaurants' in biz['categories']] restaurant_data = [rest for rest in list2 if rest['id'] in restaurant_ids]

然后restaurant_data将包含list2中包含餐馆数据的所有词典。