试图找到从python列表中聚合值(值对)的最佳方法。
foo = [
{'color': 'yellow', 'type': 'foo'},
{'color': 'yellow', 'type': 'bar'},
{'color': 'red', 'type': 'foo'},
{'color': 'red', 'type': 'foo'},
{'color': 'green', 'type': 'foo'},
{'color': 'red', 'type': 'bar'}
]
最终目标类似于
newFoo = [
{'color': 'yellow', 'type': 'foo', 'count': 1},
{'color': 'yellow', 'type': 'bar', 'count': 1},
{'color': 'red', 'type': 'foo', 'count': 2},
{'color': 'red', 'type': 'bar', 'count': 1},
{'color': 'green', 'type': 'foo', 'count': 1}
]
我对python不太满意,但是一直在尝试实现它,但是据我所知:
def loop(ar):
dik = []
for line in ar:
blah = []
for k,v in line.items():
blah.append({k,v})
blah.append({'count':'1'})
dik.append(blah)
print(dik)
任何帮助表示赞赏。
答案 0 :(得分:2)
您可以使用Counter
中的collections
:
from collections import Counter
from pprint import pprint
foo = [
{'color': 'yellow', 'type': 'foo'},
{'color': 'yellow', 'type': 'bar'},
{'color': 'red', 'type': 'foo'},
{'color': 'red', 'type': 'foo'},
{'color': 'green', 'type': 'foo'},
{'color': 'red', 'type': 'bar'}
]
c = Counter( tuple( (i['color'], i['type']) for i in foo))
pprint([{'color': k[0], 'type': k[1], 'count': v} for k, v in c.items()])
输出:
[{'color': 'yellow', 'count': 1, 'type': 'foo'},
{'color': 'yellow', 'count': 1, 'type': 'bar'},
{'color': 'red', 'count': 2, 'type': 'foo'},
{'color': 'green', 'count': 1, 'type': 'foo'},
{'color': 'red', 'count': 1, 'type': 'bar'}]
编辑:
如果要对新列表进行排序,可以执行以下操作:
l = sorted(newFoo, key=lambda v: (v['color'], v['type']), reverse=True)
pprint(l)
将打印:
[{'color': 'yellow', 'count': 1, 'type': 'foo'},
{'color': 'yellow', 'count': 1, 'type': 'bar'},
{'color': 'red', 'count': 2, 'type': 'foo'},
{'color': 'red', 'count': 1, 'type': 'bar'},
{'color': 'green', 'count': 1, 'type': 'foo'}]
编辑:
由于@MadPhysicist,您可以概括以上示例:
c = Counter(tuple(item for item in i.items()) for i in foo)
pprint([{**dict(k), 'count': v} for k, v in c.items()])
答案 1 :(得分:1)
如果您不介意重复,这是一个简单的选择。如果您只想要一个记录,那么安德烈(Andrej)的Counter
答案就很好。
newFoo = [dict(d, **{'count': foo.count(d)}) for d in foo]
>>> newFoo
[{'color': 'yellow', 'type': 'foo', 'count': 1},
{'color': 'yellow', 'type': 'bar', 'count': 1},
{'color': 'red', 'type': 'foo', 'count': 2},
{'color': 'red', 'type': 'foo', 'count': 2},
{'color': 'green', 'type': 'foo', 'count': 1},
{'color': 'red', 'type': 'bar', 'count': 1}]
答案 2 :(得分:0)
哈哈,这花了我更长的时间,我想承认,并且有很多更好的答案,但是我以一种老式的方式做到了这一点,也许这可以帮助您了解如何在没有精美库的情况下实现它。
# You clone the list before making any checks,
# because you can't iterate an empty list.
new_foo = foo
for old in foo: # for each item in the old list
for new in new_foo: # we make a check to find that item in the new one
if old['type'] == new['type'] and old['color'] == new['color']: # and if those 2 keys match
if not 'count' in new: # we try to find the count key
new['count'] = 1 # add it if it wasn't found
else:
new['count'] = new['count'] + 1 # sum 1 if it was found
break # and then stop looking, break the 2nd loop.
这应该在我们要计数的每个项目上增加计数。但是,它使重复的计数没有计数键。
{'color': 'yellow', 'type': 'foo', 'count': 1}
{'color': 'yellow', 'type': 'bar', 'count': 1}
{'color': 'red', 'type': 'foo', 'count': 2}
{'color': 'red', 'type': 'foo'}
{'color': 'green', 'type': 'foo', 'count': 1}
{'color': 'red', 'type': 'bar', 'count': 1}
当我们首先克隆列表时,可悲的是那些仍然存在于我们的新列表中,所以让我们用它来过滤掉它们。
for item in new_foo:
if not 'count' in item:
new_foo.remove(item)
结果:
{'color': 'yellow', 'type': 'foo', 'count': 1}
{'color': 'yellow', 'type': 'bar', 'count': 1}
{'color': 'red', 'type': 'foo', 'count': 2}
{'color': 'green', 'type': 'foo', 'count': 1}
{'color': 'red', 'type': 'bar', 'count': 1}
我知道有更好的答案,但是我认为在接触高级技术之前,了解基本知识很重要。我们可以通过以下方式方便地检查字典中的键并将键添加到字典中:
if 'my_made_up_key' in my_dict: # check if exists
my_dict['my_made_up_key'] = my_value # add new key to a dict
答案 3 :(得分:0)
我尽我所能使用您的原始代码。我添加的内容是对事物进行排序,然后跟踪每个项目是否与前面的项目匹配。
`# list sort/count routine`
def loop(ar):
dik = []
ar.sort() #this way we need only check the preceding one for a repeat
#it does give the list sorted, which we believe is harmless
blah={'color': '', 'type': '', 'count':0} #initialize blah to something that will not match
for line in ar:
if (blah['color']==line['color'])and (blah['type']==line['type']):
blah['count']=blah['count']+1 #still accumulating count in blah
else:#first of this one
if (blah['color'])!='':#add previous one, if any
dik.append(blah)
blah={'color': line['color'], 'type': line['type'], 'count':1}
if (blah['color'])!='':#add the last one
dik.append(blah)
return dik
foo = [
{'color': 'yellow', 'type': 'foo'},
{'color': 'yellow', 'type': 'bar'},
{'color': 'red', 'type': 'foo'},
{'color': 'red', 'type': 'foo'},
{'color': 'green', 'type': 'foo'},
{'color': 'red', 'type': 'bar'}
]
newFoo = loop(foo)
print newFoo`