我是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列表.任何帮助,将不胜感激.
>>> 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和集合2的交集,它本身就是一个集合,然后是该集合和集合3的交集.我的mysets生成器将根据需要快速地将每个集合馈送到reduce函数直到它完成.
我相信reduce已被弃用作为Python 3.0中的内置功能,但仍应在functools中使用.
您当然可以通过使用生成器表达式替换reduce中的mysets来使其成为单行,但这会降低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(reduce(find_common, mysets)) {'sum': '-21,90', 'type': 'Purchase', 'target': 'Apple Store'}
dict可以接受键,值对的任何迭代器,例如最后返回的元组集.
我的回答与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']