Python 如何加入字符串列表并删除重复的字母(保持链接) 我的名单: 期望输出: 我试过:
使用Python 如何加入字符串列表并删除重复的字母(保持链接) 我的名单: 期望输出: 我试过:,python,string,list,Python,String,List,使用itertools.groupby,但当一行中有两个重复的字母时(即leasequence->sese停留),它似乎无法正常工作: 正如您所看到的,它仅在最后一个'e'中被删除,这并不理想,因为如果一个字母有两个字符,那么它们将收缩为1。i、 e“突然”变成了“突然” 我正在寻找一种最适合这种情况的方法 先谢谢你 编辑 “我的列表”中没有任何重复项。使用辅助函数,通过删除单词的最长前缀(也是后缀s)来裁剪单词t: def crop(s, t): for k in range(len(
itertools.groupby
,但当一行中有两个重复的字母时(即leasequence
->sese
停留),它似乎无法正常工作:
正如您所看到的,它仅在最后一个'e'
中被删除,这并不理想,因为如果一个字母有两个字符,那么它们将收缩为1。i、 e“突然”
变成了“突然”
我正在寻找一种最适合这种情况的方法
先谢谢你
编辑
“我的列表”中没有任何重复项。使用辅助函数,通过删除单词的最长前缀(也是后缀
s
)来裁剪单词t
:
def crop(s, t):
for k in range(len(t), -1, -1):
if s.endswith(t[:k]):
return t[k:]
然后用前面的单词裁剪每个单词:
>>> l = ["volcano", "noway", "lease", "sequence", "erupt"]
>>> ''.join(crop(s, t) for s, t in zip([''] + l, l))
'volcanowayleasequencerupt'
>>> l = ['split', 'it', 'lit']
>>> ''.join(crop(s, t) for s, t in zip([''] + l, l))
'splitlit'
下面是一个强力重复数据消除程序:
def dedup(a, b):
for i in range(len(b), 0, -1):
if a[-i:] == b[:i]:
return a[:-i]
return a
然后,只需快速浏览:
>>> from itertools import chain, islice
>>> xs = ["volcano", "noway", "lease", "sequence", "erupt"]
>>> xs = [dedup(*x) for x in zip(xs, chain(islice(xs, 1, None), [""]))]
>>> "".join(xs)
'volcanowayleasequencerupt'
当然,这适用于任何长度的列表
xs
在我看来,这是一个更可读的版本:
from functools import reduce
def max_overlap(s1, s2):
return next(
i
for i in reversed(range(len(s2) + 1))
if s1.endswith(s2[:i])
)
def overlap(strs):
return reduce(
lambda s1, s2:
s1 + s2[max_overlap(s1, s2):],
strs, '',
)
overlap(l)
#> 'volcanowayleasequencerupt'
但是,它还考虑了以前重叠的单词中的“累积”字符:
overlap(['split', 'it', 'lit'])
#> 'split'
如果第三个单词比第二个匹配得更远,你对
l=['split','it','lit']
有什么期望?@HeapOverflow我希望'splitlit'
是这样的,规则是通过每个单词与前面的单词重叠来裁剪每个单词?@HeapOverflow是的,像这样。这对FWIW有帮助吗,这使用\uu add\uuu
,这很慢,需要为列表中的每个项目重新分配和复制最多n
。这就是O(n^2)。稍微快一点的是\uuuu iadd\uuu
。而且str.join
比CPython上的任何一个都快,因为预分配保证了O(n)
性能(以及其他方面)。@MateenUlhaq感谢您的洞察力。事实上,根据OP的要求,我选择的是“最具pythonic”而不是“最高效”的方法:“我正在为此寻找最具pythonic的方法。”
>>> from itertools import chain, islice
>>> xs = ["volcano", "noway", "lease", "sequence", "erupt"]
>>> xs = [dedup(*x) for x in zip(xs, chain(islice(xs, 1, None), [""]))]
>>> "".join(xs)
'volcanowayleasequencerupt'
from functools import reduce
def max_overlap(s1, s2):
return next(
i
for i in reversed(range(len(s2) + 1))
if s1.endswith(s2[:i])
)
def overlap(strs):
return reduce(
lambda s1, s2:
s1 + s2[max_overlap(s1, s2):],
strs, '',
)
overlap(l)
#> 'volcanowayleasequencerupt'
overlap(['split', 'it', 'lit'])
#> 'split'