生成重复列表,无论顺序如何

2024-01-11

我想生成将列表中的索引与“槽”相关联的组合。例如,(0, 0, 1)表示 0 和 1 属于同一个槽,而 2 属于另一个槽。(0, 1, 1, 1)表示 1、2、3 属于同一个槽,而 0 则单独存在。在这个例子中,0和1只是识别这些槽的方式,但不携带供我使用的信息。

最后,(0, 0, 0)完全等同于(1, 1, 1)为了我的目的,并且(0, 0, 1)相当于(1, 1, 0).

经典的笛卡尔积产生了很多我想摆脱的重复。

这就是我得到的itertools.product :

>>> LEN, SIZE = (3,1)
>>> list(itertools.product(range(SIZE+1), repeat=LEN))
>>>
[(0, 0, 0),
(0, 0, 1),
(0, 1, 0),
(0, 1, 1),
(1, 0, 0),
(1, 0, 1),
(1, 1, 0),
(1, 1, 1)]

这就是我想要得到的:

>>> [(0, 0, 0),
(0, 0, 1),
(0, 1, 0),
(0, 1, 1)]

对于小列表来说很容易,但我不太明白如何用更大的列表来做到这一点。你有什么建议吗?

如果不清楚,请告诉我,以便我澄清我的问题。谢谢你!

Edit:根据 Sneftel 的回答,这个函数似乎有效,但我不知道它是否真的产生了所有结果:

def test():
    for p in product(range(2), repeat=3):
        j=-1
        good = True
        for k in p:
            if k> j and (k-j) > 1:
                good = False
            elif k >j:
                j = k
        if good:
            yield p

我首先提出以下观察:

  1. 每个组合的第一个元素必须为 0。
  2. 第二个元素必须是 0 或 1。
  3. 第三个元素必须是 0、1 或 2,但是如果第二个元素为 1,则只能为 2.

这些观察结果表明了以下算法:

def assignments(n, m, used=0):
    """Generate assignments of `n` items to `m` indistinguishable
    buckets, where `used` buckets have been used so far.

        >>> list(assignments(3, 1))
        [(0, 0, 0)]
        >>> list(assignments(3, 2))
        [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1)]
        >>> list(assignments(3, 3))
        [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (0, 1, 2)]

    """
    if n == 0:
        yield ()
        return
    aa = list(assignments(n - 1, m, used))
    for first in range(used):
        for a in aa:
            yield (first,) + a
    if used < m:
        for a in assignments(n - 1, m, used + 1):
            yield (used,) + a

这将在几秒钟内处理您的用例(12 个项目,5 个桶):

>>> from timeit import timeit
>>> timeit(lambda:list(assignments(12, 5)), number=1)
4.513746023178101
>>> sum(1 for _ in assignments(12, 5))
2079475

这比您在答案末尾给出的函数(调用的函数)快得多product然后删除无效的分配)如果修改为处理 (12, 5) 用例,则会是这样:

>>> timeit(lambda:list(test(12, 5)), number=1)
540.693009853363
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

生成重复列表,无论顺序如何 的相关文章

随机推荐