在列表中获得所有可能的组合

时间:2011-02-24 14:51:19

标签: python list combinations

假设我有这样的事情:

L1=['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse'...]

for x in L1:
    input1= open('file_%s'%(x), 'r')
    file1= pickle.load(input1)
    for x in L1:
        input2= open('file_%s'%(x), 'r')
        file2= pickle.load(input2)

我希望获得文件的每个组合,而不重复已经完成的组合(一旦cat_dog完成,不再执行dog_cat)。有没有办法可以做到这一点?我的真实列表按字母顺序排列,如果这有任何区别的话。

6 个答案:

答案 0 :(得分:22)

实际上,您要问的是如何生成名称列表中所采用的两个项目的所有组合(而不是所有它们的可能组合)。

这意味着你可以使用内置的itertools.combinations()生成器函数轻松(并且有效地)生成所需的名称对而无需重复:

L1 = ['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse']

for pair in combinations(L1, 2):
    print(pair)
    input1 = open('file_%s' % pair[0], 'r')
    input2 = open('file_%s' % pair[1], 'r')

处理对:

('cat', 'dog')
('cat', 'fish')
('cat', 'rabbit')
('cat', 'horse')
('cat', 'bird')
('cat', 'frog')
('cat', 'mouse')
('dog', 'fish')
('dog', 'rabbit')
('dog', 'horse')
('dog', 'bird')
('dog', 'frog')
('dog', 'mouse')
('fish', 'rabbit')
('fish', 'horse')
('fish', 'bird')
('fish', 'frog')
('fish', 'mouse')
('rabbit', 'horse')
('rabbit', 'bird')
('rabbit', 'frog')
('rabbit', 'mouse')
('horse', 'bird')
('horse', 'frog')
('horse', 'mouse')
('bird', 'frog')
('bird', 'mouse')
('frog', 'mouse')

答案 1 :(得分:5)

itertools.combinations怎么样?

用法示例:

>>> list(itertools.combinations([1, 2, 3, 4, 5, 6], 2))
[(1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (2, 5), (2, 6), (3, 4),
(3, 5), (3, 6), (4, 5), (4, 6), (5, 6)]

第一个参数是可迭代的,第二个是r,返回的子序列长度。

然后,您可以轻松地使用地图或理解来连接结果:

map(lambda x: x[0] + "_" + x[1], itertools.combinations(["cat", "dog", "fish"], 2)))
lambda中的

x是一个r大小的元组。

上述结果将是:

['cat_dog', 'cat_fish', 'dog_fish']

答案 2 :(得分:5)

您也可以将其作为生成器:

L1=['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse']
tuples = [(x,y) for x in L1 for y in L1 if x != y]
for entry in tuples:
    if (entry[1], entry[0]) in tuples:
        tuples.remove((entry[1],entry[0]))
for pair in tuples:
    input1= open('file_%s'%(pair[0]), 'r')
    file1= pickle.load(input1)
    input2= open('file_%s'%(pair[1]), 'r')
    file2= pickle.load(input2)

在第一个循环之后,tuples的内容为:

('cat', 'dog')
('cat', 'fish')
('cat', 'rabbit')
('cat', 'horse')
('cat', 'bird')
('cat', 'frog')
('cat', 'mouse')
('dog', 'fish')
('dog', 'rabbit')
('dog', 'horse')
('dog', 'bird')
('dog', 'frog')
('dog', 'mouse')
('fish', 'rabbit')
('fish', 'horse')
('fish', 'bird')
('fish', 'frog')
('fish', 'mouse')
('rabbit', 'horse')
('rabbit', 'bird')
('rabbit', 'frog')
('rabbit', 'mouse')
('horse', 'bird')
('horse', 'frog')
('horse', 'mouse')
('bird', 'frog')
('bird', 'mouse')
('frog', 'mouse')

答案 3 :(得分:3)

import itertools
import cPickle

def unique_pairs(lst):
    return itertools.combinations(lst, 2)

FNAME = "file_{0}".format
def load_pickle(fname):
    with open(fname) as inf:
        return cPickle.load(inf)

def naive_method(lst):
    # load each file every time it is requested
    for x,y in unique_pairs(lst):
        input1 = load_pickle(FNAME(x))
        input2 = load_pickle(FNAME(y))
        # do something with input1 and input2

def better_method(lst):
    # if you have enough memory for it!
    dat = [load_pickle(FNAME(i)) for i in lst]
    for x,y in unique_pairs(range(len(lst))):
        input1 = dat[x]
        input2 = dat[y]
        # do something with input1 and input2

答案 4 :(得分:2)

itertools可以执行组合和排列(你需要前者)。据我所知,你不能真正指定输出格式,所以你得到“catdog”作为输出,但是doc页面让你了解组合函数的工作原理,所以你可以调整它来构建你需要什么。

答案 5 :(得分:0)

组合创建的替代方案,无需导入模块。与@ Nate的答案类似,但稍微复杂一点,创建一个包含单个项目的副本并在运行中减少(而不是生成对列表并通过列表搜索减少):

L1 = ['cat', 'dog', 'fish', 'rabbit', 'horse', 'bird', 'frog', 'mouse']
Laux = L1[:]

pairs = []
for a in L1:
    Laux.remove(a)
    for b in Laux:
        pairs += [(a,b)]