Ответ 1
values = set(map(lambda x:x[1], list))
newlist = [[y[0] for y in list if y[1]==x] for x in values]
Скажем, у меня есть список вроде этого:
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
.
ИЗМЕНИТЬ
Другое решение, которое не нуждается в импорте, более читаемо, сохраняет заказы и на 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) в худшем случае. Для больших списков с большим количеством значений ключей группировки сначала необходимо отсортировать список, а затем использовать 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']]
Edit:
Я изменил это, увидев ответ 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)]