Python列表按组大小排序

Python列表按组大小排序,python,python-2.6,itertools,sorted,Python,Python 2.6,Itertools,Sorted,我有一组项目被标记为item_labels=[('a',3),('b',2),('c',1),('d',3),('e',2),('f',3)] 我想按组的大小对它们进行排序。e、 例如,在上述示例中,标签3的尺寸为3,标签2的尺寸为2 我尝试使用groupby和sorted的组合,但没有成功 In [162]: sil = sorted(item_labels, key=op.itemgetter(1)) In [163]: sil Out[163]: [('c', 1), ('b', 2),

我有一组项目被标记为
item_labels=[('a',3),('b',2),('c',1),('d',3),('e',2),('f',3)]

我想按组的大小对它们进行排序。e、 例如,在上述示例中,标签3的尺寸为3,标签2的尺寸为2

我尝试使用
groupby
sorted
的组合,但没有成功

In [162]: sil = sorted(item_labels, key=op.itemgetter(1))

In [163]: sil
Out[163]: [('c', 1), ('b', 2), ('e', 2), ('a', 3), ('d', 3), ('f', 3)]

In [164]: g = itt.groupby(sil,)
Display all 465 possibilities? (y or n)

In [164]: g = itt.groupby(sil, key=op.itemgetter(1))

In [165]: for k, v in g:
   .....:     print k, list(v)
   .....:
   .....:
1 [('c', 1)]
2 [('b', 2), ('e', 2)]
3 [('a', 3), ('d', 3), ('f', 3)]

In [166]: sg = sorted(g, key=lambda x: len(list(x[1])))

In [167]: sg
Out[167]: [] # not exactly know why I got an empty list here

我总是可以编写一些乏味的for循环来实现这一点,但我更愿意找到更优雅的东西。有什么建议吗?如果有有用的库,我很乐意使用它。e、 例如,
pandas
scipy

itertools.groupby
返回一个迭代器,因此这个for循环:
对于k,g中的v:
实际使用了该迭代器

>>> it = iter([1,2,3])
>>> for x in it:pass
>>> list(it)          #iterator already consumed by the for-loop
[]
代码:

>>> lis = [('a', 3), ('b', 2), ('c', 1), ('d', 3), ('e', 2), ('f', 3)]
>>> from operator import itemgetter
>>> from itertools import groupby
>>> lis.sort(key = itemgetter(1) )
>>> new_lis = [list(v) for k,v in groupby(lis, key = itemgetter(1) )]
>>> new_lis.sort(key = len)
>>> new_lis
[[('c', 1)], [('b', 2), ('e', 2)], [('a', 3), ('d', 3), ('f', 3)]]
要获得展开列表,请使用
itertools.chain

>>> from itertools import chain
>>> list( chain.from_iterable(new_lis))
[('c', 1), ('b', 2), ('e', 2), ('a', 3), ('d', 3), ('f', 3)]

在python2.7及以上版本中,使用计数器:

from collections import Counter
c = Counter(y for _, y in item_labels)
item_labels.sort(key=lambda t : c[t[1]])
在python2.6中,出于我们的目的,这个
计数器
构造函数可以使用
defaultdict
(如@perreal所建议的)通过以下方式实现:

from collections import defaultdict
def Counter(x):
    d = defaultdict(int)
    for v in x: d[v]+=1
    return d
由于我们只处理数字,并且假设数字与示例中的数字一样低,我们实际上可以使用一个列表(它将与更旧版本的Python兼容):

如果没有计数器,您只需执行以下操作:

item_labels.sort(key=lambda t : len([x[1] for x in item_labels if x[1]==t[1] ]))
这是缓慢的,但合理的短名单


您得到空列表的原因是
g
是一个生成器。您只能在其上迭代一次。

与和答案相同,但使用更好的名称:

from collections import defaultdict
import operator
l=[('c', 1), ('b', 2), ('e', 2), ('a', 3), ('d', 3), ('f', 3)]
d=defaultdict(int)
for p in l: d[p[1]] += 1
print [ p for i in sorted(d.iteritems(), key=operator.itemgetter(1))
        for p in l if p[1] == i[1] ]
from collections import defaultdict

size = defaultdict(int)
for _, group_id in item_labels:
   size[group_id] += 1

item_labels.sort(key=lambda (_, group_id): size[group_id])
print item_labels
# -> [('c', 1), ('b', 2), ('e', 2), ('a', 3), ('d', 3), ('f', 3)]
还有一种方法:

example=[('a', 3), ('b', 2), ('c', 1), ('d', 3), ('e', 2), ('f', 3)]

out={}
for t in example:
    out.setdefault(t[1],[]).append(t)

print sorted(out.values(),key=len)
印刷品:

[[('c', 1)], [('b', 2), ('e', 2)], [('a', 3), ('d', 3), ('f', 3)]]
如果您想要一个简单的列表:

print [l for s in sorted(out.values(),key=len) for l in s]
[('c', 1), ('b', 2), ('e', 2), ('a', 3), ('d', 3), ('f', 3)]

不幸的是,我使用的是Python2.6,因此无法真正使用
计数器。谢谢。这一行
item\u labels.sort(key=lambda t:c[t[0]])
应该是
item\u labels.sort(key=lambda t:c[t[1]])
?您正在使用
defaultdict
@Elazar:有效地实现一个
计数器
,它在许多情况下实际上比默认dict快。试试看+1@drewk当前位置尽管在这种情况下这并不重要
print [l for s in sorted(out.values(),key=len) for l in s]
[('c', 1), ('b', 2), ('e', 2), ('a', 3), ('d', 3), ('f', 3)]