如何为每种可能的组合在列表中的项目之间添加“-”?

假设我有一个列表['a','b','1','2']。我需要以相同顺序生成此列表的所有可能组合,但要在字符之间添加破折号。

所以我需要给出以下所有答案:

a-b12
ab-12
ab1-2
a-b-12
a-b1-2
ab-1-2
a-b-1-2

我想对更长的字符串执行此操作,该字符串将具有更多的组合。我该怎么办?

编辑:伙计们,所有这些评论都非常有帮助!我非常感谢每个人帮助我解决这个问题,而不是详细解释它!

zpr6j 回答:如何为每种可能的组合在列表中的项目之间添加“-”?

a   b   1   2
  ^   ^   ^
  |   |   |
  0   1   2

想象一下,字符之间的每个空格都有一个索引。在ab之间是索引0。在b1之间是索引1。在12之间是索引2。 >

每个空间都可以连字符或不带破折号。

您要检查破折号或无任何组合。如果您将每个空间视为一个“位”,其中每个位可以为0(空)或1(破折号),则可以很好地映射到检查 b 位的所有组合,其中 b 比您拥有的商品少一。

要检查所有位组合,只需从1迭代到2 b 。 (跳过0以确保始终至少有一个破折号。)对于每次迭代,只要设置了相应的位,就插入一个破折号。

如果我们只是发出破折号或空格,而现在暂时忽略ab12字符,则是这样。

仅破折号

items = ['a','b','1','2']
bits  = len(items) - 1

for n in range(1,2**bits):
    print(''.join('-' if n & (1<<i) else ' ' for i in range(bits)))

输出

-  
 - 
-- 
  -
- -
 --
---

在后两行中发生了很多事情。让我分解一下。

  • for n in range(1,2**bits)-这是我上面解释的直接翻译。它从1循环到2 b 。唯一的区别是我称它为 bits 而不是 b 。使用更多描述性的变量名可以使代码受益。

  • (<expr> for i in range(bits)) —括号内的for循环称为generator expression。这是一种在一行代码中生成一系列项目的紧凑方法。为 i 的每个值评估 expr

  • '-' if n & (1<<i) else ' ' —上面的 expr 是这项工作。这是算法的核心:对于每个空间,我们发出一个'-'或一个' '。秘密位n & (1<<i)formula for testing if a bit is set

    如果您不熟悉&,按位AND和<<之类的按位运算,请向左移动,建议您在Google上搜索以获取更多信息。它本身就是一个非常有趣的话题,我可以花一些页面来解释。

  • ''.join(...) —将我们生成的所有'-'' '字符串连接成一个大字符串。

最后一步是散布项目和破折号。我们可以通过在上面的代码中添加几位来做到这一点。首先,我们将在每个可能的破折号之前加items[i]。其次,我们将items[-1]添加到末尾。这两个步骤有效地将破折号包围在列表中。

项目和破折号

items = ['a',2**bits):
    print(''.join(items[i] + ('-' if n & (1<<i) else '') for i in range(bits)) + items[-1])

输出

a-b12
ab-12
a-b-12
ab1-2
a-b1-2
ab-1-2
a-b-1-2
,

为清晰起见,与速度相反:

def insert( seq ):
    answers = [] 
    if seq[1:]:
        for subseq in insert( seq[1:] ):
            answers.append( [ seq[0],] + subseq )
            answers.append( [ seq[0],'-' ] + subseq )
    else:
        answers.append( seq )
    return answers

for answer in insert(['a','2'])[1:]:
    print ''.join(answer)

输出是所需的(尽管我也想输出无破折号的解决方案):

a-b12
ab-12
a-b-12
ab1-2
a-b1-2
ab-1-2
a-b-1-2
,

这是一个简单的分步解决方案。它可能比其他答案效率低下,但它是一种直接的方法。

您可以首先使用@mjwills's above comment列出n-1的所有二进制组合:

from itertools import product

lst = ['a','2']

def binary_combinations(bits):
    return list(product([0,1],repeat=bits))

binary_combs = binary_combinations(bits=len(lst) - 1)
# [(0,0),(0,1),1,(1,1)]

然后,您可以在每个项目之间插入''列表。这使得以后加入变得更容易。

def intersperse(lst,item):
    result = [item] * (len(lst) * 2 - 1)
    result[0::2] = lst
    return result

interspersed_items = intersperse(lst,'')
# ['a','','2']

最后,您可以输出替换为-str.join()的结果组合:

for comb in binary_combs[1:]:
    result = interspersed_items[:]

    for i,binary in enumerate(comb):
        if binary == 1:
            result[i * 2 + 1] = '-'

    print("".join(result))

输出以下组合。以下顺序与问题中的顺序不同,但这不应该成为问题吗?

ab1-2
ab-12
ab-1-2
a-b12
a-b1-2
a-b-12
a-b-1-2
本文链接:https://www.f2er.com/3162148.html

大家都在问