【问题标题】:Combinations of two lists in pythonpython中两个列表的组合
【发布时间】:2017-03-21 10:12:11
【问题描述】:

我有一个清单:

list = ['john','jeff','george','peter']

我想创建以下输出:

[
  [('john','jeff'),('george','peter')],
  [('john','george'),('jeff','peter')],
  [('john','peter'),('jeff','george')],
  [('george','peter'),('john','jeff')],
  [('jeff','peter'),('john','george')],
  [('jeff','george'),('john','peter')]
]

一般来说,我想为 2 对 2 游戏创建所有玩家组合。在一条输出线内,一个名字只能显示一次(一名球员一次只能在一支球队中比赛)。游戏允许进行复赛,因此每对元组都应该重复,但顺序不同(元组顺序不同,元组中项目的顺序不同)。

当列表有超过4个元素时,例如5个,输出应该是这样的:

list = ['john','jeff','george','peter','simon']

[
  [('john','jeff'),('george','peter')],
  [('john','george'),('jeff','peter')],
  [('john','george'),('jeff','simon')],
  [('john','peter'),('jeff','george')],
  [('john','simon'),('jeff','george')],
  [('george','peter'),('john','jeff')],
  [('george','simon'),('john','jeff')],
  [('jeff','peter'),('john','george')],
  [('jeff','george'),('john','peter')],
  [('jeff','george'),('john','peter')]
  ...
]

所以一场比赛总是有 4 名玩家。其余玩家只是等待,不参与特定游戏。

【问题讨论】:

  • 你试过什么,它到底有什么问题?
  • 我尝试创建两个相同的列表并使用c = list(itertools.product(list1, list2))。但它会在两边创建具有相同名称的输出。
  • 然后给出minimal reproducible example。你做过研究吗?创造一对球员是一个很好的基础。例如:stackoverflow.com/q/5360220/3001761
  • 你应该试试itertools.product(your_list, repeat=2)

标签: python


【解决方案1】:

你可以这样做:

import itertools
l = set(['john','jeff','george','peter'])
m=list(itertools.combinations(l, 2))
res=[[i,tuple(l.symmetric_difference(i))] for i in m]

m 是所有对的列表,res 将每对与它的补码相关联。所以输出是

[[('john', 'jeff'), ('peter', 'george')],
 [('john', 'peter'), ('jeff', 'george')],
 [('john', 'george'), ('jeff', 'peter')],
 [('jeff', 'peter'), ('john', 'george')],
 [('jeff', 'george'), ('john', 'peter')],
 [('peter', 'george'), ('john', 'jeff')]]

编辑:如果列表中有超过 4 个元素,这应该有效:

import itertools
l = set(['john','jeff','george','peter','a'])
four_tuples=list(itertools.combinations(l, 4))
pairs=[(set(i),list(itertools.combinations(i, 2))) for i in four_tuples]
pair_and_comp=[[[r,tuple(el[0].symmetric_difference(r))] for r in el[1:][0]] for el in pairs]
res=sum(pair_and_comp,[])
res

输出是

[[('john', 'jeff'), ('peter', 'george')],
 [('john', 'peter'), ('jeff', 'george')],
 [('john', 'george'), ('jeff', 'peter')],
 [('jeff', 'peter'), ('john', 'george')],
 [('jeff', 'george'), ('john', 'peter')],
 [('peter', 'george'), ('john', 'jeff')],
 [('john', 'jeff'), ('peter', 'a')],
 [('john', 'peter'), ('jeff', 'a')],
 [('john', 'a'), ('jeff', 'peter')],
 [('jeff', 'peter'), ('john', 'a')],
 [('jeff', 'a'), ('john', 'peter')],
 [('peter', 'a'), ('john', 'jeff')],
 [('john', 'jeff'), ('george', 'a')],
 [('john', 'george'), ('jeff', 'a')],
 [('john', 'a'), ('jeff', 'george')],
 [('jeff', 'george'), ('john', 'a')],
 [('jeff', 'a'), ('john', 'george')],
 [('george', 'a'), ('john', 'jeff')],
 [('john', 'peter'), ('george', 'a')],
 [('john', 'george'), ('peter', 'a')],
 [('john', 'a'), ('peter', 'george')],
 [('peter', 'george'), ('john', 'a')],
 [('peter', 'a'), ('john', 'george')],
 [('george', 'a'), ('john', 'peter')],
 [('jeff', 'peter'), ('george', 'a')],
 [('jeff', 'george'), ('peter', 'a')],
 [('jeff', 'a'), ('peter', 'george')],
 [('peter', 'george'), ('jeff', 'a')],
 [('peter', 'a'), ('jeff', 'george')],
 [('george', 'a'), ('jeff', 'peter')]]

【讨论】:

  • 这很好,但如果我在它创建的列表中再添加一个名称:[[('John', 'Jeff'), ('Peter', 'George', 'Simon')], [('John', 'Peter'), ('Jeff', 'George', 'Simon')], [('John', 'George'), ('Jeff', 'Peter', 'Simon')], [('John', 'Simon'), ('Jeff', 'Peter', 'George')], [('Jeff', 'Peter'), ('John', 'George', 'Simon')], [('Jeff', 'George'), ('John', 'Peter', 'Simon')], [('Jeff', 'Simon'), ('John', 'Peter', 'George')]]。所以第二个元组的大小是 3 而不是 2,并且没有所有的组合。
  • 那么如果有 5 个玩家,你希望第二个元组是什么?
  • 哦,我没说。对不起。当有超过 4 名玩家时,所有剩余的玩家只需暂停特定游戏并等待。所以总是有 4 个玩家,但由所有玩家生成。我想生成所有可用游戏的列表(所以每个人都必须玩所有生成的游戏)。
  • 那么您绝对应该将其添加到问题中
  • @sennin - 我添加了一个我认为满足您需求的答案。
【解决方案2】:

以下内容如何:

from itertools import combinations
from pprint import pprint

names = ['john', 'jeff', 'george', 'peter', 'ringo']

combos = list(combinations(names, 2))
pairs = [[x, y] for x in combos for y in combos if not set(x).intersection(set(y))]

pprint(pairs)

combinations 为我们提供了所有长度为 2 的对(我们将其转换为 list,因此在迭代它时不会耗尽它)。 set(x).intersection(set(y)) 查找xy 之间是否有任何共同项,如果不是,我们希望保留组合。

打印出来:

[[('john', 'jeff'), ('george', 'peter')],
 [('john', 'jeff'), ('george', 'ringo')],
 [('john', 'jeff'), ('peter', 'ringo')],
 [('john', 'george'), ('jeff', 'peter')],
 [('john', 'george'), ('jeff', 'ringo')],
 [('john', 'george'), ('peter', 'ringo')],
 [('john', 'peter'), ('jeff', 'george')],
 [('john', 'peter'), ('jeff', 'ringo')],
 [('john', 'peter'), ('george', 'ringo')],
 [('john', 'ringo'), ('jeff', 'george')],
 [('john', 'ringo'), ('jeff', 'peter')],
 [('john', 'ringo'), ('george', 'peter')],
 [('jeff', 'george'), ('john', 'peter')],
 [('jeff', 'george'), ('john', 'ringo')],
 [('jeff', 'george'), ('peter', 'ringo')],
 [('jeff', 'peter'), ('john', 'george')],
 [('jeff', 'peter'), ('john', 'ringo')],
 [('jeff', 'peter'), ('george', 'ringo')],
 [('jeff', 'ringo'), ('john', 'george')],
 [('jeff', 'ringo'), ('john', 'peter')],
 [('jeff', 'ringo'), ('george', 'peter')],
 [('george', 'peter'), ('john', 'jeff')],
 [('george', 'peter'), ('john', 'ringo')],
 [('george', 'peter'), ('jeff', 'ringo')],
 [('george', 'ringo'), ('john', 'jeff')],
 [('george', 'ringo'), ('john', 'peter')],
 [('george', 'ringo'), ('jeff', 'peter')],
 [('peter', 'ringo'), ('john', 'jeff')],
 [('peter', 'ringo'), ('john', 'george')],
 [('peter', 'ringo'), ('jeff', 'george')]]

【讨论】:

  • 您以不同的顺序返回相同的答案两次。
  • @beniev 是的,故意如此 - 正如问题所说,“游戏允许进行重赛,所以每对元组都应该重复,但顺序不同”
  • 是的,这个答案似乎还可以
【解决方案3】:

这应该对你有用:

from itertools import combinations
l = ['john','jeff','george','peter','beni']
x= list(combinations(l,2))
y=list(combinations(x,2))
remove_dup =lambda y: y if len(set(y[0])-set(y[1]))==2 else None
answer=[remove_dup(t) for t in y if remove_dup(t) is not None]

答案:

[(('john', 'jeff'), ('george', 'peter')),
 (('john', 'jeff'), ('george', 'beni')),
 (('john', 'jeff'), ('peter', 'beni')),
 (('john', 'george'), ('jeff', 'peter')),
 (('john', 'george'), ('jeff', 'beni')),
 (('john', 'george'), ('peter', 'beni')),
 (('john', 'peter'), ('jeff', 'george')),
 (('john', 'peter'), ('jeff', 'beni')),
 (('john', 'peter'), ('george', 'beni')),
 (('john', 'beni'), ('jeff', 'george')),
 (('john', 'beni'), ('jeff', 'peter')),
 (('john', 'beni'), ('george', 'peter')),
 (('jeff', 'george'), ('peter', 'beni')),
 (('jeff', 'peter'), ('george', 'beni')),
 (('jeff', 'beni'), ('george', 'peter'))]

【讨论】:

    【解决方案4】:

    permutations()试试itertools

    import itertools
    my_list = ['john','jeff','george','peter']
    paired = []
    for pair in itertools.permutations(my_list, 2):
        paired.append(pair)
    print paired
    

    [('约翰', '杰夫'), (“约翰”,“乔治”), ('约翰','彼得'), ('杰夫','约翰'), ('杰夫','乔治'), ('杰夫','彼得'), (“乔治”,“约翰”), (“乔治”,“杰夫”), (“乔治”,“彼得”), (“彼得”,“约翰”), (“彼得”,“杰夫”), ('彼得', '乔治')]

    【讨论】:

    • @sennin,试试这个。这是获得所需输出的最简单方法。
    • 你两次返回同一对 - 你没有返回补码......
    猜你喜欢
    • 1970-01-01
    • 2022-11-03
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多