如何在python中的所有组合列表中知道其索引中的元素组合

时间:2016-10-28 15:48:21

标签: python combinations itertools

我有一些列表中的所有配对组合:

a = [1,2,3,4,5,6]
pairs = [pair for pair in itertools.combinations(a,2)]
print pairs

>>>[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]

如果我只知道它的索引,我怎么知道我使用的对是什么? 也许有一些公式?问题是我的名单太大了,我不能记住所有对。我只需要一些我可以通过索引识别的特定对。

有什么建议吗?

谢谢!

4 个答案:

答案 0 :(得分:4)

这是一种直接从索引生成对的方法。这可能是一个更有效的方程式,但这是我几分钟后想出来的。 :)

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))

<强>输出

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

这是一个改进版本,在长度为500的列表上比前一个版本快10倍,并且在更大的列表上应该更高效。

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]

我不会试图完全解释它是如何工作的,但它使用triangular numbers

设p(x)为第x个三角形数,即从1到x的数字之和。 T(x)的公式很简单:

T(x) = x * (x + 1) / 2

假设y = T(x),我们可以通过反转上面的公式计算x

x = (8*y + 1) ** 0.5 - 1) / 2

答案 1 :(得分:3)

找到一个给定索引的对:

my_pair = pairs[index]

找一个索引*给出一对:

index = pairs.index(my_pair)

*如果列表中有多个实例,则会给出my_pair第一个实例的索引。

答案 2 :(得分:3)

所以...... itertools.combinations给你一个迭代器(见this):

>>> import itertools
>>> a = [1,2,3,4,5,6]
>>> itertools.combinations(a,2)
<itertools.combinations object at 0x10ca841d8>

这意味着在请求项目本身之前,它不会将所有可能的项目都放在内存中。

一个快速的解决方案就是只保留你想要的物品。例如,如果您只想保留最后一项(或pair[1])等于4的对,您可以这样做:

>>> pairs = [ pair for pair in itertools.combinations(a,2) if pair[1] == 4 ]
>>> pairs
[(1, 4), (2, 4), (3, 4)]

(假设pair[1]就是你所说的 index

如果它仍然太大,你可能需要实现自己的迭代器,所以你不要预先加载内存中的所有项目,而只是在请求时计算它们。

如果您所谓的 index 是该对中的第一项,您可以以类似的方式使用它。例如,我们假设您只想要第一项(pair[0])等于2的项目:

>>> pairs = [ pair for pair in itertools.combinations(a,2) if pair[0] == 2 ]
>>> pairs
[(2, 3), (2, 4), (2, 5), (2, 6)]

这样可行......但如果是这种情况,如果你使用itertools.product可能会更好,如下所示:

>>> [a for a in itertools.product([2], [5, 6, 7])]
[(2, 5), (2, 6), (2, 7)]

或使用map将函数应用于iterable中的每个项...

>>> [a for a in map(lambda x: (2, x), [1, 2, 3])]
[(2, 1), (2, 2), (2, 3)]

答案 3 :(得分:-2)

如果你有一个索引,并且想要知道该值,那么只需使用pairs[index]

即可