【问题标题】:How to generate permutations of a list without “moving” zeros. in Python如何在不“移动”零的情况下生成列表的排列。在 Python 中
【发布时间】:2016-06-09 13:32:18
【问题描述】:

使用itertools 工具,我拥有给定数字列表的所有可能排列,但如果列表如下:

List=[0,0,0,0,3,6,0,0,5,0,0]

itertools 不“知道”迭代零是浪费工作,例如以下迭代将出现在结果中:

List=[0,3,0,0,0,6,0,0,5,0,0]

List=[0,3,0,0,0,6,0,0,5,0,0]

它们是相同的,但 itertools 只取第一个零(例如)并将其移动到列表中的第四位,反之亦然。

问题是:我怎样才能只迭代一些选定的数字而不管其他数字,比如零?它可以有或没有itertools

【问题讨论】:

  • 使用类似output2 = list(set(output))的东西,其中output是你从itertools得到的。
  • 我需要在列表中的所有位置迭代一些数字,只留下零。
  • 你来了。 (我的新方法,第三种方法,答案)

标签: python list permutation


【解决方案1】:

瞧——它现在可以工作了——在得到“肉”的排列之后,我进一步得到了“0”位置和产量的所有可能组合 每个排列的每个可能的“0位置”集合的一个排列 非0:

from itertools import permutations, combinations

def permut_with_pivot(sequence, pivot=0):
    pivot_indexes = set()
    seq_len = 0
    def yield_non_pivots():
        nonlocal seq_len
        for i, item in enumerate(sequence):
            if item != pivot:
                yield item
            else:
                pivot_indexes.add(i)
        seq_len = i + 1

    def fill_pivots(permutation):
        for pivot_positions in combinations(range(seq_len), len(pivot_indexes)):
            sequence = iter(permutation)
            yield tuple ((pivot if i in pivot_positions else next(sequence)) for i in range(seq_len))

    for permutation in permutations(yield_non_pivots()):
        for filled_permutation in fill_pivots(permutation):
            yield filled_permutation

(我使用了 Python 的 3“nonlocal”关键字——如果你还在使用 Python 2.7, 您将不得不采取另一种方法,例如使 seq_len 成为一个包含单个项目的列表,然后您可以在内部函数上替换)

我的第二次尝试(实际工作的是第三次)

这是一种简单的方法,它只保留已经“看到”的排列的缓存 - 它节省了对每个排列所做的工作,而不是生成所有可能排列的工作:

from itertools import permutations

def non_repeating_permutations(seq):
    seen = set()
    for permutation in permutations(seq):
        hperm = hash(permutation)
        if hperm in seen:
            continue
        seen.add(hperm)
        yield permutation

【讨论】:

  • 现在您需要查看 n 的分区,其中 n 是原始列表中零的数量。非零元素 (k) 的数量也很重要,因为它们定义了允许的分区类型。例如,如果 k = 3,如上例所示,每个分区可以表示为 k+1 个值的总和,但不能更多。
  • @V.Petretto 但您不想修复它们,是吗??
  • 不,我不想修复它们,让我写一个输出示例:[0,0,1,0,8] [0,1,0,8,0] [1 ,0,8,0,0] [1,8,0,0,0] [8,0,1,0,0] 等等
  • (留下这个只是为了说明上面的 cmets 是关于这个答案的早期版本。当前算法确实置换了 0)
  • 非常感谢! :)
【解决方案2】:

将每个结果附加到列表中。现在您将拥有所有可能的组合,然后执行以下操作:

list(set(your_big_list))

Set 会将列表缩小到唯一的排列。 我不完全确定这是您要解决的问题还是您担心性能。 不管怎样,我刚刚注册了一个帐户,所以我想我会尝试贡献一些东西

【讨论】:

  • 我看到你的方法的唯一问题是它的计算效率低下。必须有更好的方法。
  • 是的,我要解决的问题是性能和速度。使用大量数字列表,例如 30 或更多,程序运行时间太长,并且浪费了大量工作,因此效率不高。
  • SetList 甚至都不是 Python 内置的。也许你的意思是listset
  • 更不用说这不仅会丢掉所有的零,而且会丢掉一个零(以及它们的位置)以及任何其他重复
  • 是的,解决了这些大写问题。
【解决方案3】:

您的问题不清楚,但如果您尝试在输出中没有 0 的情况下列出排列,您可以按以下方式进行:

from itertools import permutations
def perms( listy ):
    return permutations( [i for i in listy if i!=0])

【讨论】:

  • 我不认为这是他想要的,但这可以作为它的基础。您现在可以用 0 填充您的排列以生成更多组合,每个组合都具有原始列表的长度☺
  • 我需要输出中的 0 但我不需要它成为排列的一部分。这是为了避免重复输出和 CPU 工作丢失。也许我可以创建一个基本的零列表,然后在其中插入置换后的数字?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 2016-05-24
  • 1970-01-01
  • 1970-01-01
  • 2018-06-13
  • 2019-09-08
  • 1970-01-01
相关资源
最近更新 更多