计算itertools.product()的第n个结果

时间:2018-12-05 06:39:57

标签: python python-3.x combinations itertools combinatorics

我正在尝试计算itertools.product()的第n个结果

test = list(product('01', repeat=3))
print(test)

desired_output = test[0]
print(desired_output)

所以没有得到:

[('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')

但是,您可能已经猜到了,它的伸缩性不好。这就是为什么我只尝试计算第n个值的原因。

我通读了 Nth Combination,但我需要product()提供的重复功能

谢谢!

2 个答案:

答案 0 :(得分:5)

可以很容易地仿真repeat功能。这是this博客文章中描述的Ruby代码的python版本。

def product_nth(lists, num):
    res = []
    for a in lists:
        res.insert(0, a[num % len(a)])
        num //= len(a)

    return ''.join(res)

将此函数称为

>>> repeats = 50
>>> chars = '01'
>>> product_nth([chars] * repeats, 12345673)
'00000000000000000000000000101111000110000101001001'

这里有一些时间测试:

repeat = 50
idx = 112345673

%timeit i = product_nth(['01'] * repeat, idx)
%%timeit
test = product('01', repeat=repeat)
one = islice(test, idx, idx+1)
j = ''.join(next(one))

2.01 s ± 22.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
36.5 µs ± 201 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

print(i == j)
True

另一个答案是误导性的,因为它误解了islice的功能。例如,请参见:

def mygen(r):
    i = 0
    while i < r:
        print("Currently at", i)
        yield i
        i += 1

list(islice(mygen(1000), 10, 11))

# Currently at 0
# Currently at 1
# Currently at 2
# Currently at 3
# Currently at 4
# Currently at 5
# Currently at 6
# Currently at 7
# Currently at 8
# Currently at 9
# Currently at 10
# Out[1203]: [10]

islice将逐步完成每个单次迭代,并丢弃结果,直到指定索引为止。对product的输出进行切片时,会发生同样的事情-对于较大的N,该解决方案效率不高。

答案 1 :(得分:2)

如果您构建了整个列表,那么由于调用java RN2N贯穿整个迭代器,当然不能很好地扩展。

如果只需要第一个值,则可以使用list()提取迭代器的第一个值。这不需要构建整个列表,而且很快。

您还可以使用next(test)来获得迭代器的特定部分,而无需建立整个列表,而且速度非常快。但是要知道,它仍然会迭代到第N个值。这是执行此操作的一种非常Python化的方法,它具有内存高效且易于阅读的特点。是否足够快取决于您的N需要多大。例如,这为我很快产生了第200000个组合的值:

itertools.islice()