Самый быстрый способ создания декартового произведения без дублирующих элементов внутри пары
У меня есть список индексов изображений, и его длина составляет 60000. Я хочу создать еще один список, который содержит случайные пары индексов. Ограничение здесь заключается в том, что каждый элемент набора продуктов должен содержать различные индексы. Другими словами, я не хочу связывать индекс с этим самостоятельно.
В настоящее время я использую itertools.product
метод с for
петля.
pairs = []
for pair in itertools.product(indexes, indexes):
if pair[0]!=pair[1]:
pairs.append(pair)
На решение проблемы уходит много времени, и я не могу использовать свой компьютер, потому что он зависает.
Есть ли лучший способ сделать это?
4 ответа
Вы можете сделать это лениво, не сохраняя их:
pairs = filter(lambda x: x[0] != x[1], itertools.product(indexes, indexes))
использование itertools.ifilter
при использовании python2
Идея использования itertools состоит в том, что вам не нужно предварительно вычислять все, а просить вычислять его по одному элементу (вычислению) за раз.
Я сделал сравнение времени, предложенное @Deepak Saini, которое здесь живет:
import numpy as np
import itertools
indexes = np.arange(1000)
def pairs(indexes):
pairs = []
for pair in itertools.product(indexes, indexes):
if pair[0]!=pair[1]:
pairs.append(pair)
return pairs
def iter_pairs(indexes):
return filter(lambda x: x[0] != x[1], itertools.product(indexes, indexes))
def iter_pairs_no_lambda(indexes):
def comp(x):
return x[0] != x[1]
return filter(comp, itertools.product(indexes, indexes))
import time
for f in (pairs, iter_pairs, iter_pairs_no_lambda):
print(f.__name__)
t1 = time.time()
res = f(indexes)
print("Took {}".format(time.time() - t1))
Который приводит к:
pairs
Took 1.012538194656372
iter_pairs
Took 0.04567384719848633
iter_pairs_no_lambda
Took 0.0002455711364746094
import numpy as np
a = np.asarray(indexes)
b = np.copy(a)
while np.any(a == b):
b = np.random.choice(a, size=a.shape[0], replace=False)
И должно быть очень быстро
Numpy решение с использованием tile
, repeat
а также transpose
,
temp = np.transpose([np.tile(indexes, len(indexes)), np.repeat(indexes, len(indexes))])
pairs = temp[temp[:,0] != temp[:,1]]
Сроки сравнения: я сравниваю время с
# @Netwave solution
list(filter(lambda x: x[0] != x[1], itertools.product(indexes, indexes)))
Нам нужно преобразовать генератор в список для честного сравнения.
На
indexes = np.arange(5000)
сроки:
Netwave решение: 20,623 с
Numpy решение: 3.302 с
Убедитесь, что у вас есть уникальные значения, а затем выберите комбинацию из двух из них.
list(itertools.combinations(set(indexes), 2))