我是Python的新手,我遇到了一个问题,我无法用谷歌来解决这个问题。我使用wxPython和ObjectiveListView构建了一个GUI。在它的中心,GUI有一个列表控件,以X行显示数据(数据由用户加载)和五列。
当用户从列表控件中选择多个条目(按下CTRL或单击时移位)时,ObjectiveListView模块会给我一个字典列表,这些字典包含列表控件行中的数据。这正是我想要的,好!
返回的列表如下所示:
print MyList
[{'id':1023, 'type':'Purchase', 'date':'23.8.2008', 'sum':'-21,90', 'target':'Apple Store'}, {'id':1024, 'type':'Purchase', 'date':'24.8.2008', 'sum':'-21,90', 'target':'Apple Store'}, {'id':23, 'type':'Purchase', 'date':'2.8.2008', 'sum':'-21,90', 'target':'Apple Store'}]
所有词典都具有相同的键,但值会发生变化。 'id'值是唯一的。这里出现了问题。我想获取用户选择的所有项目的公共值。在上面的列表中,它们将是'sum':' - 21,90'和'target':'Apple Store'。
我不知道如何正确比较列表中的dicts。一个大问题是我事先不知道列表包含多少个词,因为它是由用户决定的。
我有一个模糊的想法,列表推导将是要走的路,但我只知道如何将两个列表与列表推导进行比较,而不是n列表。任何帮助将不胜感激。
答案 0 :(得分:7)
>>> mysets = (set(x.items()) for x in MyList)
>>> reduce(lambda a,b: a.intersection(b), mysets)
set([('sum', '-21,90'), ('type', 'Purchase'), ('target', 'Apple Store')])
首先,我创建了一个生成器,它将dicts列表转换为一组可重复的键值对。你可以在这里使用列表理解,但是这种方式不会将你的整个列表转换成另一个列表,如果你不知道它有多大,那就很有用。
然后我使用reduce来应用一个函数来找到每个集合之间的公共值。它找到了集合1和1的交集。设置2,它本身就是一个集合,然后是该集合的交集。设置3等myset生成器将根据需要快速地将每个集合提供给reduce函数,直到完成。
我认为reduce已被弃用为Python 3.0中的内置功能,但仍应在functools中使用。
当然,您可以通过使用生成器表达式替换reduce中的myset来使其成为单行,但这会降低IMO的可读性。在实践中,我甚至可能更进一步,将lambda打破到自己的行中:
>>> mysets = (set(x.items()) for x in MyList)
>>> find_common = lambda a,b: a.intersection(b)
>>> reduce(find_common, mysets)
set([('sum', '-21,90'), ('type', 'Purchase'), ('target', 'Apple Store')])
如果您需要将最终结果作为dict,请将其包装起来:
>>> dict(reduce(find_common, mysets))
{'sum': '-21,90', 'type': 'Purchase', 'target': 'Apple Store'}
dict可以接受键,值对的任何迭代器,例如最后返回的元组集。
答案 1 :(得分:7)
我的回答与Matthew Trevor相同,除了一个区别:
>>> mysets = (set(x.items()) for x in MyList)
>>> reduce(set.intersection, mysets)
set([('sum', '-21,90'), ('type', 'Purchase'), ('target', 'Apple Store')])
这里我使用set.intersection
而不是创建一个新的lambda。在我看来,这更具可读性,因为这直观地读作“减少使用集合交集运算符减少此列表”。这也应该快得多,因为set.intersection
是一个内置的C函数。
要完全回答您的问题,您可以使用列表解析来提取值:
>>> mysets = (set(x.items()) for x in MyList)
>>> result = reduce(set.intersection, mysets)
>>> values = [r[1] for r in result]
>>> values
['-21,90', 'Purchase', 'Apple Store']
这对我来说最终会排在第一线。但这完全取决于你:
>>> [r[1] for r in reduce(set.intersection, (set(x.items()) for x in myList))]
['-21,90', 'Purchase', 'Apple Store']
答案 2 :(得分:2)
首先,我们需要一个函数来计算两个字典的交集:
def IntersectDicts( d1, d2 ) :
return dict(filter(lambda (k,v) : k in d2 and d2[k] == v, d1.items()))
然后我们可以用它来处理任意数量的词典:
result = reduce(IntersectDicts, MyList)
答案 3 :(得分:1)
由于您只是在查找公共集,因此您可以将第一个字典中的键与所有其他词典中的键进行比较:
common = {}
for k in MyList[0]:
for i in xrange(1,len(MyList)):
if MyList[0][k] != MyList[i][k]: continue
common[k] = MyList[0][k]
>>> common
{'sum': '-21,90', 'type': 'Purchase', 'target': 'Apple Store'}
答案 4 :(得分:0)
对不起,是的,'输入':'购买'也是常见值之一。应该已登录编辑问题。