是否有 Python 函数可以在两个等长字符串之间进行所有可能的替换?
Is there a Python function to make all possible substititutions between two equal length strings?
我正在尝试在参考序列和测试序列之间进行所有可能的替换。序列将始终具有相同的长度,目标是用 Ref.
的字符替换测试字符
Ref= "AAAAAAAAA"
Test="AAATAATTA"
期望的输出:
AAATAATTA, AAATAAAAA, AAATAATAA, AAATAATTA, AAAAAATTA, AAAAAATAA, AAAAAAATA
如果将两个字符串 zip
放在一起(将它们变成一组 2 元组供 product
查找组合),则可以使用 itertools.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
函数接受任意数量的可迭代对象作为参数;我们想使用 *
:
将我们所有的二元组作为单独的参数提供给它
>>> [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)
通过将其设为集合推导式 ({}
) 而不是列表推导式 ([]
),我们只获得唯一元素。
如果您想避免使用 itertools
(as .product
will make more copies of equal strings in your case), You can use recursion
and generators
并实施您自己的解决方案。我的倾向是,如果这些序列非常大,那么出于这个原因,这应该会更高效。但是,如果不是,那么 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
字符串,如果您真的不想包含它,可以在最后将其从结果中删除。
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
我正在尝试在参考序列和测试序列之间进行所有可能的替换。序列将始终具有相同的长度,目标是用 Ref.
的字符替换测试字符Ref= "AAAAAAAAA"
Test="AAATAATTA"
期望的输出:
AAATAATTA, AAATAAAAA, AAATAATAA, AAATAATTA, AAAAAATTA, AAAAAATAA, AAAAAAATA
如果将两个字符串 zip
放在一起(将它们变成一组 2 元组供 product
查找组合),则可以使用 itertools.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
函数接受任意数量的可迭代对象作为参数;我们想使用 *
:
>>> [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)
通过将其设为集合推导式 ({}
) 而不是列表推导式 ([]
),我们只获得唯一元素。
如果您想避免使用 itertools
(as .product
will make more copies of equal strings in your case), You can use recursion
and generators
并实施您自己的解决方案。我的倾向是,如果这些序列非常大,那么出于这个原因,这应该会更高效。但是,如果不是,那么 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
字符串,如果您真的不想包含它,可以在最后将其从结果中删除。
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