Here's a way to generate a pair directly from its index. There's probably a more efficient equation for this, but this is what I came up with after a couple of minutes. :)
import itertools
def pair_from_index(a, i):
m = n = len(a) - 1
while i >= n:
i -= n
n -= 1
m -= n
return a[m], a[m + i + 1]
# test
a = list('abcdefg')
for i, t in enumerate(itertools.combinations(a, 2)):
print(i, t, pair_from_index(a, i))
output
0 ('a', 'b') ('a', 'b')
1 ('a', 'c') ('a', 'c')
2 ('a', 'd') ('a', 'd')
3 ('a', 'e') ('a', 'e')
4 ('a', 'f') ('a', 'f')
5 ('a', 'g') ('a', 'g')
6 ('b', 'c') ('b', 'c')
7 ('b', 'd') ('b', 'd')
8 ('b', 'e') ('b', 'e')
9 ('b', 'f') ('b', 'f')
10 ('b', 'g') ('b', 'g')
11 ('c', 'd') ('c', 'd')
12 ('c', 'e') ('c', 'e')
13 ('c', 'f') ('c', 'f')
14 ('c', 'g') ('c', 'g')
15 ('d', 'e') ('d', 'e')
16 ('d', 'f') ('d', 'f')
17 ('d', 'g') ('d', 'g')
18 ('e', 'f') ('e', 'f')
19 ('e', 'g') ('e', 'g')
20 ('f', 'g') ('f', 'g')
Here's an improved version that's about 10 times faster than the previous one on lists of length 500, and it should be even more efficient on larger lists.
def pair_from_index(a, i):
n = len(a) - 1
m = n * (n + 1) // 2
y = m - i - 1
d = 1 + int(((8*y + 1) ** 0.5 - 1) / 2)
k = n - d
return a[k], a[1 + i + k + d * (d + 1) // 2 - m]
I won't try to explain completely how it works, but it uses triangular numbers.
Let T(x) be the x'th triangular number, i.e., the sum of the numbers from 1 to x. The formula for T(x) is simple:
T(x) = x * (x + 1) / 2
Given y = T(x) we can calculate x by inverting the above formula
x = (8*y + 1) ** 0.5 - 1) / 2
pairs[ind][0]or some other detail? i.e. will you Not Know the contents of thepairbeforehand?I need only some particular pairs which I can recognise by index.You could get the combinations ofenumerate(a)which would include the indexing in that data if you mean the index ofa