【问题标题】:Shuffling combinations without converting iterable (itertools.combinations) to list改组组合而不将可迭代(itertools.combinations)转换为列表
【发布时间】:2016-04-21 20:24:24
【问题描述】:

以下简单代码为我提供了 200 个元素中长度为 3 的可能组合。

from itertools import combinations
comb = combinations( range(200), 3 )

我想以随机顺序获取组合,以便选择前 N 个组合。但是,如果我将 comb 转换为列表并按以下方式对其进行随机播放,则可能会出现内存错误,因为列表可能包含太多元素:

comb = list(comb) # This might be huge and give a memory error 
random.shuffle(comb)
N = 10
comb = comb[:10] # get only the first N random combinations

还有其他方法可以得到 N 个随机组合吗? (即,不是按照 itertools.combinations 生成的顺序)。

【问题讨论】:

    标签: python combinations shuffle itertools


    【解决方案1】:

    C(200, 3) = 1313400 可能的组合。正如您还提到的,由于combinatorial explosion,这个数字很容易失控。例如,如果您选择 4 个而不是 3 个元素,则组合的数量将大约增加 50 倍 (64684950)。您可以随机构建可能的组合,而不是从这些组合中随机选择。

    要构建这些组合,您可以使用随机库中的random.samplerandom.sample(range(200), 3) 将随机生成这 1313400 个组合之一。如果再次调用它,它将生成另一个组合。

    有两个问题:

    1. random.sample 中的顺序很重要([1, 2, 3] 与 [1, 3, 2] 不同)。在组合中,它不是。要解决这个问题,您可以使用sorted()
    2. random.sample 将独立生成接下来的 3 个数字。因此,在不同的迭代中产生的组合可能是相同的。虽然这个例子不太可能(≈0.0000343),但您可以使用一个集合来存储组合,以便只存储唯一的组合。

    以下将生成 10 种不同的组合:

    import random
    combs = set()
    N = 10
    while len(combs) < N:
        combs.add(tuple(sorted(random.sample(range(200), 3))))
    

    【讨论】:

    • 这个答案没有利用迭代器的属性
    • @mprat 我认为迭代器在这种情况下没有任何优势。在下面的函数中,您分配了pool = tuple(iterable)。如果您使用 random_combination(comb, 10) 调用该函数,它将生成所有可能的组合并将它们存储在名为 pool 的变量中。这正是 OP 试图避免的。
    • @mprat:这根本不是流操作;迭代器没有优势。即使您的答案(取自itertools 文档)也零使用itertools 或迭代器操作;它仅在 itertools 文档中列出,因为它与 itertools.combinations 相关。
    • @ayhan:你可能在 itertools 上太费劲了。 itertools 文档中的random_combination 函数不打算以mprat 使用它的方式使用。这个想法是你会在range(200)而不是comb上调用它,它会给你一个随机组合,而不是实现所有组合; pool 只会实现 range(200)
    • @user2357112 我不能确定,因为那时功能与random.sample基本相同。唯一的区别是它选择索引而不是元素,但这应该不会有太大变化。
    猜你喜欢
    • 1970-01-01
    • 2021-04-21
    • 2012-05-07
    • 1970-01-01
    • 2016-08-06
    • 2015-02-21
    • 2021-08-26
    • 1970-01-01
    • 2018-07-13
    相关资源
    最近更新 更多