是否有一个 Python 函数可以在两个相等长度的字符串之间进行所有可能的替换?

Posted

技术标签:

【中文标题】是否有一个 Python 函数可以在两个相等长度的字符串之间进行所有可能的替换?【英文标题】:Is there a Python function to make all possible substititutions between two equal length strings? 【发布时间】:2020-08-12 10:40:25 【问题描述】:

我正在尝试在参考序列和测试序列之间进行所有可能的替换。序列将始终具有相同的长度,目标是用参考字符替换测试字符。

Ref= "AAAAAAAAA"
Test="AAATAATTA"

期望的输出:

AAATAATTA, AAATAAAAA,  AAATAATAA,  AAATAATTA,  AAAAAATTA,  AAAAAATAA,  AAAAAAATA

【问题讨论】:

这是否意味着对于字符串长度中的每个 i,new_string 中的第 i 个字符可以是 Ref[i]Tests[i]?从而创建2^len -1 可能的new_strings,其中len = len(Ref)?但是,您只需要在 Ref[i] ~= Test[i]? 时进行这些替换? 【参考方案1】:

如果您将zip 两个字符串放在一起,则可以为此使用itertools.product(将它们变成一组2 元组供product 查找组合)。然后,您可能希望将它们统一在一个集合中。总而言之,它看起来像这样:

>>> ''.join(t) for t in product(*zip(Ref, Test))
'AAAAAAAAA', 'AAAAAATAA', 'AAAAAAATA', 'AAATAATTA', 'AAATAATAA', 'AAATAAAAA', 'AAATAAATA', 'AAAAAATTA'

为了进一步分解它,因为如果您不熟悉相关功能,它看起来有点像线路噪音......

这是zip,它将我们的两个字符串转换为对的迭代(将其包装在列表推导中以便于打印,但我们将在下一阶段将其删除):

>>> [t for t in zip(Ref, Test)]
[('A', 'A'), ('A', 'A'), ('A', 'A'), ('A', 'T'), ('A', 'A'), ('A', 'A'), ('A', 'T'), ('A', 'T'), ('A', 'A')]

product 函数接受任意数量的迭代作为参数;我们想使用 * 将我们所有的 2 元组作为单独的参数提供给它:

>>> [t for t in product(*zip(Ref, Test))]
[('A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'), ('A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'), ... (a whole lot of tuples)

使用join 将这些元组转回字符串:

>> [''.join(t) for t in product(*zip(Ref, Test))]
['AAAAAAAAA', 'AAAAAAAAA', 'AAAAAAATA', 'AAAAAAATA', ... (still a whole lot of strings)

通过将其设为集合推导 () 而不是列表推导 ([]),我们得到的只是唯一元素。

【讨论】:

【参考方案2】:

itertools.combinations可用于生成位置组合,可以在itertools.combinations的第二个参数处控制元组大小

import itertools

REF = "AAAAAAAAA"
poses =(3,6,7)
for i in range(1, len(poses) + 1):
    tmp = itertools.combinations(poses, i)
    for j in tmp:
        result = REF
        print(j)
        for k in j:
            result = result[:k]+'T' + result[k+1:]
        print(result)

结果:

(3,)
AAATAAAAA
(6,)
AAAAAATAA
(7,)
AAAAAAATA
(3, 6)
AAATAATAA
(3, 7)
AAATAAATA
(6, 7)
AAAAAATTA
(3, 6, 7)
AAATAATTA

【讨论】:

【参考方案3】:

如果您想避免使用itertools(因为.product 会在您的情况下制作更多相同字符串的副本),您可以使用recursiongenerators 并实施您自己的解决方案。我的倾向是,如果这些序列非常大,这应该会更有效率。但是,如果不是,那么itertools 解决方案会更好。

def take_some(to: str, from_: str):
     assert len(to) == len(from_)  # your precondition
     if to == from_:  # no-more left to check ('' == '') in worst case
         yield from_
         return
     for i, (l, r) in enumerate(zip(to, from_)):
          if l != r:
               # do not take the character
               rest = take_some(to[i+1:], from_[i+1:])
               for res in rest:
                   yield to[:i+1] + res
                   yield to[:i] + r + res
               return

给予

In [2]: list(take_some("AAAAAAAAA", "AAATAATTA"))                                     
['AAAAAAAAA',
 'AAATAAAAA',
 'AAAAAATAA',
 'AAATAATAA',
 'AAAAAAATA',
 'AAATAAATA',
 'AAAAAATTA',
 'AAATAATTA']

请注意,这确实包含原始的Ref 字符串,如果您真的不想包含它,可以在最后将其从结果中删除。

【讨论】:

以上是关于是否有一个 Python 函数可以在两个相等长度的字符串之间进行所有可能的替换?的主要内容,如果未能解决你的问题,请参考以下文章

两个字符串几乎相等

检查两个排序的字符串在 O(log n) 时间内是不是相等

strcmp(a,b),比较时是不是要求两个字符串的长度相等??

python如何判断两个数组完全相等?

第11条:用zip函数同时遍历两个迭代器

c++怎么判断两数相等