Performance_Python根据元组的3个元素中的2个获得2个元组列表的并集

时间:2010-11-18 02:37:35

标签: python list union tuples

我的计划做得不好。在一个循环中,来自每个处理器(元组列表)的数据被收集到主处理器中,需要通过删除类似的元素来清理它。

我在网上找到了很多有趣的线索,特别是在这个网站上关于列表的联合。但是,我还没有设法将它应用于我的问题。 我的目标是摆脱其最后两个元素与列表中另一个元组相似的元组。例如:

list1=[[a,b,c],[d,e,f],[g,h,i]]
list2=[[b,b,c],[d,e,a],[k,h,i]]
the result should be:
final=[[a,b,c],[d,e,f],[g,h,i],[d,e,a]]

现在我正在使用循环和休息,但我希望能让这个过程更快。

这是我的代码看起来像什么(结果和临时是我想要联合的列表) 在python2.6上。

for k in xrange(len(temp)):
    u=0
    #index= next((j for j in xrange(lenres) if temp[k][1:3] == result[j][1:3]),None)
    for j in xrange(len(result)):
        if temp[k][1:3] == result[j][1:3]:
            u=1
            break
    if u==0:
    #if index is None:
        result.append([temp[k][0],temp[k][1],temp[k][2]])

感谢您的帮助

的Herve

2 个答案:

答案 0 :(得分:1)

以下是我们的唯一功能。它接受参数l(列表)和f(函数),返回列表,删除重复(按相同的顺序)。重复项定义如下:b是iff f(b)== f(a)的副本。

def uniques(l, f = lambda x: x):
    return [x for i, x in enumerate(l) if f(x) not in [f(y) for y in l[:i]]]

我们将lastTwo定义如下:

lastTwo = lambda x: x[-2:]

对于您的问题,我们按如下方式使用它:

>>> list1
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i')]
>>> list2
[('b', 'b', 'c'), ('d', 'e', 'a'), ('k', 'h', 'i')]
>>> uniques(list1+list2, lastTwo)
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i'), ('d', 'e', 'a')]

如果你描述的用例出现很多,你可能想要定义

def hervesMerge(l1, l2):
    return uniques(l1+l2, lambda x: x[-2:])

Identity是我们的默认f,但它可以是任何东西(只要它是为列表的所有元素定义的,因为它们可以是任何类型)。

f可以是列表的总和,列表的奇数元素,整数的素数因子,任何东西。 (只要记住,如果它的内射性没有意义!通过常数,线性函数等添加将与身份bc没有区别,其f(x)== f(y)w / x!= y可以产生差异)

>>> list1
[(1, 2, 3, 4), (2, 5), (6, 2, 2), (3, 4), (8, 3), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]
>>> uniques(list1, sum)
[(1, 2, 3, 4), (2, 5), (8, 3)]
>>> uniques(list1, lambda x: reduce(operator.mul, x))  #product
[(1, 2, 3, 4), (2, 5), (3, 4), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]
>>> uniques([1,2,3,4,1,2]) #defaults to identity
[1, 2, 3, 4]

你似乎对速度感到担忧,但我的回答确实集中在短暂性/灵活性上而没有显着的(或任何?)速度提升。对于需要关注速度的较大列表,您希望利用可清除检查以及已知list1和list2没有重复的事实

>>> s = frozenset(i[-2:] for i in list1)
>>> ans = list(list1) #copy list1
>>> for i in list2:
        if i[-2:] not in s: ans.append(i)
>>> ans
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i'), ('d', 'e', 'a')]

或允许无序化

>>> d = dict()
>>> for i in list2 + list1:
        d[i[-2:]] = i
>>> d.values()
[('d', 'e', 'f'), ('a', 'b', 'c'), ('g', 'h', 'i'), ('d', 'e', 'a')]   

- 编辑 -

你应该始终能够像你在问题中发帖一样避免非pythonic循环。以下是更改循环的确切代码:

for k in temp:
  u=0
  for j in result:
      if k[1:3] == j[1:3]:
          u=1
          break
  if u==0:
  #if index is None:
      result.append([k[0],k[1],k[2]])   // k

结果和temp是可迭代的,对于任何可迭代的东西,你可以将它直接放在for循环中而不需要eanges。如果由于某种原因你明确需要索引(这不是这种情况,但我上面有一个)你可以使用枚举。

答案 1 :(得分:1)

这是一个使用集合的简单解决方案:

list1=[('a','b','c'),('d','e','f'),('g','h','i')]
list2=[('b','b','c'),('d','e','a'),('k','h','i')]

set1 = set([A[1:3] for A in list1])
final = list1 + [A for A in list2 if A[1:3] not in set1]

但是,如果list1和list2实际上不是由元组组成的,那么你必须将tuple()放在A [1:3]周围。