Вычисление n-го результата для itertools.product () - PullRequest
0 голосов
/ 05 декабря 2018

Я пытаюсь вычислить n-й результат для itertools.product ()

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-е значение.

Я прочитал N-ую комбинацию , но мне нужна функция повторения, которую product () предлагает

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Если вы строите весь список, если, конечно, не будете хорошо масштабироваться, потому что вызов list() проходит через весь итератор.

Если вам нужно только первое значение, вы можете просто использовать next(test) вытащить первое значение итератора.Это не требует построения всего списка и будет очень быстрым.

Вы также можете использовать itertools.islice(), чтобы получить определенную часть итератора, не выстраивая весь список, и это довольно быстро.Но поймите, что он все равно будет повторяться до N-го значения.Это очень питонический способ сделать это, он эффективно использует память и легко читается.Достаточно ли быстро это зависит от того, насколько большим должен быть ваш N.Например, для меня довольно быстро получается значение 200000-й комбинации:

from itertools import product, islice

test = product('01', repeat=20)
one = islice(test, 200000, 200001)
print(''.join(next(one)))

# 00110000110101000000
0 голосов
/ 05 декабря 2018

Функциональность repeat может быть смоделирована довольно легко.Вот Python-версия кода Ruby, описанного в этом сообщении в блоге.

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'

Вот несколько тестов timeit:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...