Как я могу присоединиться к списку строк и удалить дублированные буквы (держать их в цепочке) - PullRequest
4 голосов
/ 27 января 2020

Мой список:

l = ["volcano", "noway", "lease", "sequence", "erupt"]

Желаемый вывод:

'volcanowayleasequencerupt'

Я пробовал:

с использованием itertools.groupby, но похоже, что это не работает хорошо, когда в строке 2 повторяющихся буквы (т.е. leasesequence -> sese остается):

>>> from itertools import groupby
>>> "".join([i[0] for i in groupby("".join(l))])
'volcanonowayleasesequencerupt'

Как вы можете видеть, он избавился только за последние 'e', и это не идеально, потому что если буква содержит двойные символы, они будут сокращены до 1. т. е. 'suddenly' становится 'sudenly'.

Я ищу наиболее подход Pythoni c для этого.

Заранее спасибо.

РЕДАКТИРОВАТЬ

В моем списке нет дублирующихся элементов.

Ответы [ 3 ]

4 голосов
/ 27 января 2020

Использование вспомогательной функции, которая обрезает слово t, удаляя его самый длинный префикс, который также является суффиксом s:

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'
2 голосов
/ 27 января 2020

Более читаемая версия, на мой взгляд:

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'
1 голос
/ 27 января 2020

Вот дедупликатор грубой силы:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...