【问题标题】:Pythonic random list of booleans of length n with exactly k Trues长度为 n 且恰好为 k 的布尔值的 Pythonic 随机列表
【发布时间】:2014-05-30 20:10:45
【问题描述】:

假设我们想要一个 n 0/1 元素列表,其中包含 k1 实例。是否有比以下更简单的单行理解或更 Pythonic 的方式来做到这一点?

def random_include(n, k):
    ret = []
    to_include = set(random.sample([i for i in range(n)], k))
    for i in range(n): 
        if i in to_include:
            ret.append(1)
        ret.append(0)

【问题讨论】:

    标签: python list random


    【解决方案1】:
    def random_include(n, k):
        my_list = [1] * k + [0] * (n - k)
        random.shuffle(my_list)
        return my_list
    

    先用足够多的 1 和 0 构造列表。

    my_list = [1] * k + [0] * (n - k)
    

    然后随机播放

    random.shuffle(my_list)
    

    【讨论】:

    • 美观紧凑! +1。
    【解决方案2】:

    使用random.shuffle (documentation):

    random_list = [False] * j + [True] * k
    random.shuffle(random_list)
    

    会给你一个随机列表,jFalsekTrue

    请注意,实现自定义 shuffle 算法通常会出现问题,因为编写一个产生看似随机结果但不提供恒定概率分布的算法非常容易。 IE。有些序列比其他序列更有可能!

    Jeff Atwood's blog post 对此主题进行了广泛探讨。正确的解决方案是使用Fisher-Yates algorithm,如果你想要一个正确的洗牌序列,这正是random.shuffle() 所做的:

    def shuffle(self, x, random=None, int=int):
        randbelow = self._randbelow
        for i in reversed(range(1, len(x))):
            # pick an element in x[:i+1] with which to exchange x[i]
            j = randbelow(i+1) if random is None else int(random() * (i+1))
            x[i], x[j] = x[j], x[i]
    

    因此,最好还是依靠random.shuffle(),而不是想出一个聪明的方法来自己洗牌!

    【讨论】:

    • 感谢您对我的解决方案的反馈。这只是出于好奇,但为什么random.shuffle() 使用random() 函数这一事实不会对Fisher-Yates 造成问题?根据 Wikipedia 关于算法的文章,似乎 PRNG 也有问题。
    • 是的,PRNGs with small states give uneven probability distributions。 Python 随机模块 (Modules/_randommodule.c) 使用 624 个长整数 = 19968 位内部状态。因此,洗牌一副约 2000 张牌将达到其绝对极限(math.log2(math.factorial(2083)) 约为2**19968)。如果您正在改组少于 100-200 个元素的序列,您应该是安全的。很好的讨论,顺便说一句。谢谢。
    【解决方案3】:

    这是一个单行解决方案。

    output = sorted([1] * k + [0] * (n - k), key=lambda k: random.random())
    

    【讨论】:

    • 就我个人而言,我发现明确的random.shuffle 更具可读性。如果一年后你来看看random.shuffle,就会立即清楚发生了什么。这个实现不是这样。
    • @ChristianAichinger,我完全同意,但为了解决 OP 的单线解决方案要求,这确实满足了他的要求。 :)
    • 此外,shuffling is hard。您真的需要像Fisher-Yates shuffle 这样的算法来确保正确的概率分布!你确定sorted() 方法不会落入那个陷阱吗?
    • @merlin2011 似乎您通过评估第一个参数然后不打扰另一个,因为第一个是真的。 ;)
    • @ChristianAichinger,我当然不确定。但我同样不确定来自同一个 Python 库的 random.shuffle() 会做得更好。
    【解决方案4】:

    试试:

    random.sample([1] * k + [0] * (n - k), n)
    

    这会返回你想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2015-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多