按值分组
比方说,我有这样一个列表:
list = [["A",0], ["B",1], ["C",0], ["D",2], ["E",2]]
我怎样才能最优雅的组合这个得到这个列表输出在Python中:
list = [["A", "C"], ["B"], ["D", "E"]]
所以这些值是按secound值分组的,但顺序是保留的。
values = set(map(lambda x:x[1], list)) newlist = [[y[0] for y in list if y[1]==x] for x in values]
from operator import itemgetter from itertools import groupby lki = [["A",0], ["B",1], ["C",0], ["D",2], ["E",2]] lki.sort(key=itemgetter(1)) glo = [[x for x,y in g] for k,g in groupby(lki,key=itemgetter(1))] print glo
。
编辑
另一种不需要导入的解决scheme更具有可读性,可以保持订单,比前一版本长22%
oldlist = [["A",0], ["B",1], ["C",0], ["D",2], ["E",2]] newlist, dicpos = [],{} for val,k in oldlist: if k in dicpos: newlist[dicpos[k]].extend(val) else: newlist.append([val]) dicpos[k] = len(dicpos) print newlist
霍华德的回答简洁而优雅,但在最坏的情况下也是O(n ^ 2)。 对于包含大量分组键值的大型列表,您需要先对列表进行sorting,然后使用itertools.groupby
:
>>> from itertools import groupby >>> from operator import itemgetter >>> seq = [["A",0], ["B",1], ["C",0], ["D",2], ["E",2]] >>> seq.sort(key = itemgetter(1)) >>> groups = groupby(seq, itemgetter(1)) >>> [[item[0] for item in data] for (key, data) in groups] [['A', 'C'], ['B'], ['D', 'E']]
编辑:
在看到eyequem的答案后,我改变了这个: itemgetter(1)
比lambda x: x[1]
更好。
>>> import collections >>> D1 = collections.defaultdict(list) >>> for element in L1: ... D1[element[1]].append(element[0]) ... >>> L2 = D1.values() >>> print L2 [['A', 'C'], ['B'], ['D', 'E']] >>>
我不知道优雅,但肯定是可行的:
oldlist = [["A",0], ["B",1], ["C",0], ["D",2], ["E",2]] # change into: list = [["A", "C"], ["B"], ["D", "E"]] order=[] dic=dict() for value,key in oldlist: try: dic[key].append(value) except KeyError: order.append(key) dic[key]=[value] newlist=map(dic.get, order) print newlist
这保留了每个键的第一次出现的顺序,以及每个键的项目顺序。 它要求密钥是可哈希的,但是并不赋予其意义。
len = max(key for (item, key) in list) newlist = [[] for i in range(len+1)] for item,key in list: newlist[key].append(item)
你可以在一个单一的列表理解,也许更优雅,但O(n ** 2):
[[item for (item,key) in list if key==i] for i in range(max(key for (item,key) in list)+1)]