在保持结构的同时从任意嵌套列表中随机抽样

时间:2018-01-24 03:32:32

标签: python list random

我正在尝试编写一个函数,该函数从任意嵌套列表中随机选择整数,同时保持顺序和列表结构(尽管可以忽略空列表)。样本数应该从0到嵌套列表中的整数数均匀随机。

例如,运行listrand([1,2,3,[3,4],[65,[3]]]) 3次可能会给出:

[1, 3, [3], [65, [3]]]
[1, 2, [[3]]]
[[3, 4], [65]]

问题是,我需要它是均匀分布的,所以我不能使用像

这样的东西
sample = [[random.sample(mylist)] for mylist in listoflists]

因为那会是二项式的。

至少我需要这个才能用于单级嵌套。我想从扁平列表中抽样,但后来我不确定如何使用这些来构建所需的输出。

1 个答案:

答案 0 :(得分:3)

此解决方案通过构造满足您的要求。换句话说,所选元素的数量是均匀随机的。

import random
from collections import Iterable

def count(l, r=0):
    for i in l:
        if isinstance(i, Iterable):
            r += count(i)
        else:
            r += 1
    return r

def listrand(target):
    N = count(target)
    nchosen = random.randint(0, N-1)
    chosen = set(random.sample(range(N), nchosen))

    def build(l, c=0):
        output = []
        for i in l:
            if isinstance(i, Iterable):
                c, sublist = build(i, c)
                if sublist:
                    output.append(sublist)
            else:
                if c in chosen:
                    output.append(i)
                c += 1
        return c, output

    return build(target)[1]        

示例输出:

target = [1,2,3,[3,4], [65,[3]]]

for i in range(5):
    print(listrand(target))

[1, 2, 3, [3, 4], [[3]]]
[2]
[]
[2, 3, [3, 4]]
[[4]]