【问题标题】:Performance_Python get union of 2 lists of tuple according to 2 out of the 3 elements of the tuplePerformance_Python 根据元组的 3 个元素中的 2 个获取 2 个元组列表的并集
【发布时间】:2010-11-18 02:37:34
【问题描述】:

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

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

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]]

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

这是我的代码的样子(result 和 temp 是我想从中获得联合的列表) 在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]])

感谢您的帮助

赫维

【问题讨论】:

  • 顺便说一下,列表[...] 不是元组(...),两者的性能可能不同。

标签: python list union tuples


【解决方案1】:

下面是我们的独特功能。它接受参数 l(列表)和 f(函数),返回删除重复项的列表(以相同的顺序)。重复定义为: b 是 a 的重复,当且仅当 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

result 和 temp 是可迭代的,对于任何可迭代的内容,您都可以将其直接放入 for 循环中而无需 eanges。如果由于某种原因您明确需要索引(不是这种情况,但我上面有一个),您可以使用 enumerate。

【讨论】:

  • 对不起,如果我走神了。我喜欢你的问题并把它变成了我自己的一个项目=P
  • 谢谢!使用 lambda 是我的想法,但我不知道该怎么做。
  • 很高兴你喜欢。我发布了一个不同的解决方案,专注于您的确切速度问题,这就是您所问的。您应该接受其中一个答案。除了勾搭你接受的人,这会让人们在未来更有可能回答你。还会为您赢得一枚漂亮的徽章
  • 再次感谢。这非常整洁。我不知道所有接受答案的事情。我花了一段时间,但我想我设法通过单击您答案旁边的检查来接受您的答案。看来只能接受一个答案了……
【解决方案2】:

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

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] 周围。

【讨论】:

  • 你确定吗? final 的结尾几乎与您列出的所需结果完全相同。它怎么不工作?
  • 抱歉...出于某种原因,当我将您的代码复制到我的 python shell 时,我收到了错误消息。阅读您的消息后,我再次尝试,正如您所说,它确实有效。抱歉,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-07
  • 1970-01-01
  • 2020-10-01
  • 2019-04-19
  • 1970-01-01
  • 2011-09-27
相关资源
最近更新 更多