【问题标题】:Quickest way to remove mirror opposites from a list从列表中删除镜像对立的最快方法
【发布时间】:2017-07-12 12:21:29
【问题描述】:

假设我有一个元组列表[(0, 1, 2, 3), (4, 5, 6, 7), (3, 2, 1, 0)],我想删除所有反转元组的实例,例如从上面的列表中删除 (3, 2, 1, 0)

我目前的(基本)方法是:

L = list(itertools.permutations(np.arange(x), 4))

for ll in L:
    if ll[::-1] in L:
        L.remove(ll[::-1])

所用时间随着 x 的增加呈指数增长。因此,如果 x 很大,这需要很长时间!如何加快速度?

【问题讨论】:

  • 在循环浏览列表时从列表中删除内容是个坏主意。
  • 您是否删除 (3, 2, 1, 0) 而不是 (0, 1, 2, 3) 仅仅是因为后者先出现?
  • 删除哪个并不重要
  • 但在您的示例代码中,您正在创建一个包含 x permute 4 元素的列表。这等于 x*(x-1)*(x-2)*(x-3)。这是一个 4 阶多项式,本质上增长非常快—— O(x^4)。例如,如果 x = 100,则 L 包含近 1 亿个元素。当然,使用这个例子你的代码会很慢。
  • 那么你要做什么就不清楚了。你的代码并不慢是因为你的算法,你的代码很慢是因为它必须创建你选择的巨大的示例列表。但是你把问题说成好像列表可以是任何东西一样?

标签: python logic itertools


【解决方案1】:

想到使用set

L = set()
for ll in itertools.permutations(np.arange(x), 4):
    if ll[::-1] not in L:
        L.add(ll)

甚至,为了更好的性能:

L = set()
for ll in itertools.permutations(np.arange(x), 4):
    if ll not in L:
        L.add(ll[::-1])

【讨论】:

  • 但即使 ll 的逆存在于 list \ set 中,您确实希望在结果中出现其中之一.. 这是棘手的一点。
  • @Ev.Kounis 所以我添加一个,如果另一个还没有没有添加。
  • 另外,请注意这种方法如何通过创建临时列表来减少内存使用。
【解决方案2】:

需要保持第一个看起来像它迫使你用一个有条件的迭代。

a = [(0, 1, 2, 3), (4, 5, 6, 7), (3, 2, 1, 0)]
s = set(); a1 = []
for t in a:
    if t not in s:
        a1.append(t)
        s.add(t[::-1])

编辑: 接受的答案涉及示例代码(即 itertools 排列示例)。这回答了任何列表(或可迭代)的通用问题。

【讨论】:

  • 不需要 a1。如果你真的需要一个列表,list(s) 会生成它。
  • @Błotosmętek 理解,但它不会保持秩序。它不会真正类似于删除反向复制品的原版。
  • 我在 OP 对问题的描述中没有看到保留顺序的要求……
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-27
  • 2010-11-23
  • 1970-01-01
  • 1970-01-01
  • 2015-07-30
  • 2010-12-13
  • 1970-01-01
相关资源
最近更新 更多