我正在运行一个Python脚本作为Hadoop流媒体作业,但这篇文章与一些核心Python概念有关,而不是关于Hadoop的知识。
基本上我有一组行,我想找到重叠
$ cat sample.txt
ID1 2143,2154,
ID2 2913,14545
ID3 2143,2390,3350,5239,6250
ID4 2143,2154,2163,3340
ID5 2143,2154,2156,2163,3340,3711
我想最终找到重叠的记录对并计算它们,例如:
2143,2154 3
2143,2163 2
2143,3340 2
2154,2163 2
2154,3340 2
2163,3340 2
我这样做的方法是创建一个用Python编写的Hadoop流作业,其中mapper将基本输出给定行上的所有对组合,并由reducer进一步处理。
我的问题实际上很简单:如何在Python中生成高效给定行中所有对的组合?请注意,在我的情况下,一对(x,y)与一对(y,x)相同。例如,对于ID3
,我想在我的映射器中生成以下列表:
[(2143,2390), (2143,2390), (2143,3350), (2143,5239), (2143,6250), (2390,3350), (2390,5239), (2390,6250), (3350,5239), (3350,6250), (5239,6250)]
我当然可以通过一堆for循环来做到这一点,但它非常难看。我尝试过使用itertools,却无法正确使用它。有什么想法吗?
答案 0 :(得分:8)
怎么样:
x = [2143, 2390, 3350, 5239, 6250]
itertools.combinations(x, 2)
给出:
(2143, 2390) (2143, 3350) (2143, 5239) (2143, 6250) (2390, 3350) (2390, 5239) (2390, 6250) (3350, 5239) (3350, 6250) (5239, 6250)
答案 1 :(得分:2)
如果l
是有问题的列表
[(x, y) for x in l for y in l if x < y]
或者,您可以创建一个生成器:
def pairs(l):
for x in l:
for y in l:
if x < y:
yield x, y
这样做的好处是能够“动态”生成对,而不必同时将它们全部保存在内存中。
使用itertools.product(l, l)
可以实现类似的功能,但这会生成(x, y) and (y, x)
,并且还会生成(x, x)
之类的对。要过滤掉这些内容,您必须执行以下操作:
itertools.ifilter(lambda (x,y): x < y, itertools.product(l,l))
答案 2 :(得分:2)
琐碎的
有什么不对for i, x in enumerate(L):
for y in L[i+1:]:
whatever(x, y)
这将调用whatever
传递来自L
的每个不同元素对(不同的意思是不同的索引,如果L
包含重复项,它们可能相等)。