Вместо кортежей и повторяющихся i
, вы можете в основном просто хранить j
-значения:
l = []
prefixsum = [0]
for i in range(A):
J = [j for j in range(B) if predicate(i,j)]
l.append(J)
prefixsum.append(prefixsum[-1]) + len(J))
Затем для заданного k
, выполнить бинарный поиск в prefixsum
, чтобы получить i
, а затем найдите j
в списке.
Кроме того, вместо списков int
объектов вы также можете использовать Python массивы из 4-байтов. int (или 3-байтовые int с некоторой дополнительной работой). NumPy массивов, которые также могут ускорить все вычисления.
Грубый тест, игнорирующий некоторые издержки, на 64-битном Python:
# A list of 100 tuples takes 888 bytes (just the list object)
> l = [(10**6, 10**6 + j) for j in range(100)]
> l = [(10**l.__sizeof__()
888
# The tuples take 4000 bytes
> l = [(10**sum(t.__sizeof__() for t in l)
4000
# The i-value takes 28 bytes
> l[0][0].__sizeof__()
28
# The j-values take 2800 bytes
sum(j.__sizeof__() for _, j in l)
2800
Так что это 7716 байт для списка 100 кортежей 2-х целых. Теперь array
из j
-значений:
> a = array.array('I', (j for i, j in l))
> a = array.a.__sizeof__()
472
Это в 16 раз меньше памяти.