我有一个清单
l=[(1,2),(1,6),(3,4),(3,6),(1,4),(4,3)]
我想返回一个列表,其中包含每个元组中第一个数字的列表。 像这样:
[[2,4,6],[4,6],[3]]
制作一个迭代列表并编写完整函数的程序很容易。 我想找到一个oneliner - python这样做的方式。 有什么想法吗?
答案 0 :(得分:10)
>>> from itertools import groupby
>>> from operator import itemgetter
>>> L = [(1,2), (1,6), (3,4), (3,6), (1,4), (4,3)]
>>> [[y for x, y in v] for k, v in groupby(sorted(L), itemgetter(0))]
[[2, 4, 6], [4, 6], [3]]
<强>解释强>
这可以通过使用itertools.groupby
来实现。 groupby
在iterable中找到连续组,通过键组对返回迭代器。
赋予groupby
的参数是一个关键函数,itemgetter(0)
为每个元组调用,返回第一个项作为groupby
的键。
groupby
对原始订单中的元素进行分组,因此,如果您希望按列表中的第一个数字进行分组,则必须先对其进行排序,以便groupby
可以通过第一个数字按升序排列并实际分组。
>>> sorted(L)
[(1, 2), (1, 4), (1, 6), (3, 4), (3, 6), (4, 3)]
有一个排序列表,您可以清楚地看到如果您回顾最终输出将创建的组。现在,您可以使用groupby
来显示密钥,组对。
[(1, <itertools._grouper object at 0x02BB7ED0>), (3, <itertools._grouper object at 0x02BB7CF0>), (4, <itertools._grouper object at 0x02BB7E30>)]
以下是按第一个数字分组的排序项目。 groupby
将每个键的组作为迭代器返回,这非常有效且非常有效但是对于此示例,我们只需将其转换为list
以确保其正常工作。
>>> [(k, list(v)) for k,v in groupby(sorted(L), itemgetter(0))]
[(1, [(1, 2), (1, 4), (1, 6)]), (3, [(3, 4), (3, 6)]), (4, [(4, 3)])]
这几乎是正确的,但所需的输出只显示每个列表中组中的第二个数字。因此,以下方法可以达到预期的效果。
[[y for x, y in v] for k, v in groupby(sorted(L), itemgetter(0))]
答案 1 :(得分:2)
l = [(1, 2), (1, 6), (3, 4), (3, 6), (1, 4), (4, 3)]
d = {}
for (k, v) in l:
d.setdefault(k, []).append(v)
print d.values()
我知道这不是一个班轮,但也许它比一个班轮更容易阅读。