将列表中的每个元素与 n 个列表中的每个元素进行组合

3
我将尽力通过一个例子来解释,因为我似乎有点难以说明清楚:
假设我有一个字符串列表和另一个字符串列表的列表:
words = ["hello", "goodbye", "foo"]
lists = [["111", "450", "nice"], ["can", "be", "of", "different", "sizes"]]

我希望将第一个列表中的1个项目与n个列表中的1个项目相结合,例如:

n = 1:

hello111
hello450
hellonice
hellocan
hellobe
...

或者 n = 2

hello111can
hello111be
hello111of
...

在这种情况下,n = 3是不可能的。

我正在尝试使用Python的itertools库中的product或其他方法,但似乎无法理解如何实现。

[编辑] 我标记为正确答案的回答是我想要的,但需要使用排列而不是组合,请谢谢!


我认为我理解了n==1的例子,但是我不明白n==2的情况应该如何工作。 - timgeb
1
请以n=2和三个子列表为例,展示一般情况的示例! - tobias_k
当n=2时,您想要hello111can和hellocan111两个结果还是只需要第一个? - FCo
hellocan111 对于 n=2 是一个好的案例吗? - FunkySayu
我认为你需要使用itertools组合和join函数来实现你想要的功能。 - gkusner
这是一个笛卡尔积,通过连接字符串进行一些后处理。 - Nayuki
2个回答

1
首先,使用 itertools.combinations(lists, n) 获取来自 listsn 个元素的组合,然后使用 itertools.product(words, *comb) 获取原始单词和该组合中元素的乘积。您可以将这两个步骤组合成一个双循环列表推导式:
>>> n = 1
>>> [x for comb in itertools.combinations(lists, n) for x in itertools.product(words, *comb)]
[('hello', '111'),
 ('hello', '450'),
 ('hello', 'nice'),
 ('goodbye', '111'),
 ...
 ('foo', 'sizes')]

或者对于 n = 2:
[('hello', '111', 'can'),
 ('hello', '111', 'be'),
 ('hello', '111', 'of'),
 ('hello', '111', 'different'),
 ('hello', '111', 'sizes'),
 ('hello', '450', 'can'),
 ...
 ('foo', 'nice', 'sizes')]

n = 3及以上时,您将得到[]

最后,只需''.join它们在一起。(我没有这样做,以使其更易读。)

>>> [''.join(x) for comb in itertools.combinations(lists, n) for x in itertools.product(words, *comb)]

他需要一个字符串列表。应该用 "".join(x) 替换 x,以得到 OP 想要的结果。 - heinst
@heinst 是的,这正是我在上一行中所说的。不过,我觉得使用列表会使组合更加明确。 - tobias_k
啊,我没看到那个!抱歉! - heinst

1
from itertools import combinations, product

words = ["hello", "goodbye", "foo"]
lists = [["111", "450", "nice"], ["can", "be", "of", "different", "sizes"]]

# how many elements of `lists` to pick from?
for n in range(1, len(lists) + 1):
    # This returns in-order combinations, ie you will get
    # '111', 'can'  and not 'can', '111'.
    # If you want all orderings as well as all combinations,
    # use itertools.permutations instead,
    for sublist in combinations(lists, n):
        # now we generate all combinations of
        # one element from each basis list,
        basis = [words] + list(sublist)
        for combo in product(*basis):
            # and display the result
            print("".join(combo))

这提供了

hello111
hello450
hellonice
goodbye111
goodbye450
goodbyenice
foo111
foo450
foonice
hellocan
hellobe
helloof
hellodifferent
hellosizes
goodbyecan
goodbyebe
goodbyeof
goodbyedifferent
goodbyesizes
foocan
foobe
fooof
foodifferent
foosizes
hello111can
hello111be
hello111of
hello111different
hello111sizes
hello450can
hello450be
hello450of
hello450different
hello450sizes
hellonicecan
hellonicebe
helloniceof
hellonicedifferent
hellonicesizes
goodbye111can
goodbye111be
goodbye111of
goodbye111different
goodbye111sizes
goodbye450can
goodbye450be
goodbye450of
goodbye450different
goodbye450sizes
goodbyenicecan
goodbyenicebe
goodbyeniceof
goodbyenicedifferent
goodbyenicesizes
foo111can
foo111be
foo111of
foo111different
foo111sizes
foo450can
foo450be
foo450of
foo450different
foo450sizes
foonicecan
foonicebe
fooniceof
foonicedifferent
foonicesizes

那会先生成 n=1,再生成 n=2、n=3 等。如果您不关心顺序,可以尝试以下方法:
for word in words:
    combos = product(*([""] + sublist for sublist in lists))
    next(combos)   # skip n=0
    for combo in combos:
        print(word + "".join(combo))

which produces

hellocan
hellobe
helloof
hellodifferent
hellosizes
hello111
hello111can
hello111be
hello111of
hello111different
hello111sizes
hello450
hello450can
hello450be
hello450of
hello450different
hello450sizes
hellonice
hellonicecan
hellonicebe
helloniceof
hellonicedifferent
hellonicesizes
goodbyecan
goodbyebe
goodbyeof
goodbyedifferent
goodbyesizes
goodbye111
goodbye111can
goodbye111be
goodbye111of
goodbye111different
goodbye111sizes
goodbye450
goodbye450can
goodbye450be
goodbye450of
goodbye450different
goodbye450sizes
goodbyenice
goodbyenicecan
goodbyenicebe
goodbyeniceof
goodbyenicedifferent
goodbyenicesizes
foocan
foobe
fooof
foodifferent
foosizes
foo111
foo111can
foo111be
foo111of
foo111different
foo111sizes
foo450
foo450can
foo450be
foo450of
foo450different
foo450sizes
foonice
foonicecan
foonicebe
fooniceof
foonicedifferent
foonicesizes

(同样的列表,不同的顺序)。


你不能在函数外使用yield。 - heinst
不错的男士 ;) 正是我需要的,但包括你提到的排列组合!你们怎么理解这个问题的,天呐!真的很棒,谢谢。 - Esser420

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接