Оптимизация покрытия строк в Python - PullRequest
5 голосов
/ 13 ноября 2010

У меня есть эта начальная строка.

'bananaappleorangestrawberryapplepear'

А также есть кортеж со строками:

('apple', 'plepe', 'leoran', 'lemon')

Мне нужна функция, чтобы из исходной строки и кортежа со строками я получил это:

'bananaxxxxxxxxxgestrawberryxxxxxxxar'

Я знаю, как сделать это обязательно, находя слово в начальной строке для каждого слова, а затем зацикливая символ за символом во всей начальной строке с замененными словами.

Но это не очень эффективно и безобразно. Я подозреваю, что должен быть какой-то способ сделать это более элегантно, функционально, с помощью itertools или чего-то еще. Если вы знаете библиотеку Python, которая может сделать это эффективно, пожалуйста, дайте мне знать.

ОБНОВЛЕНИЕ : Джастин Пил указал случай, который я не описал в своем первоначальном вопросе. Если слово «aaa» и «aaaaaa» находится в исходной строке, вывод должен выглядеть как «xxxxxx».

Ответы [ 6 ]

3 голосов
/ 13 ноября 2010
import re

words = ('apple', 'plepe', 'leoran', 'lemon')
s = 'bananaappleorangestrawberryapplepear'

x = set()

for w in words:
    for m in re.finditer(w, s):
        i = m.start()
        for j in range(i, i+len(w)):
            x.add(j)

result = ''.join(('x' if i in x else s[i]) for i in range(len(s)))
print result

производит:

bananaxxxxxxxxxgestrawberryxxxxxxxar
1 голос
/ 14 ноября 2010
>>> string_ = 'bananaappleorangestrawberryapplepear'
>>> words = ('apple', 'plepe', 'leoran', 'lemon')
>>> xes = [(string_.find(w), len(w)) for w in words]
>>> xes
[(6, 5), (29, 5), (9, 6), (-1, 5)]
>>> for index, len_ in xes:
...   if index == -1: continue
...   string_ = string_.replace(string_[index:index+len_], 'x'*len_)
...
>>> string_
'bananaxxxxxxxxxgestrawberryxxxxxxxar'
>>>

Конечно, есть более эффективные способы, но преждевременная оптимизация - корень всех зол.

1 голос
/ 13 ноября 2010

При условии, что мы ограничены в работе без stdlib и другого импорта:

s1 = 'bananaappleorangestrawberryapplepear'
t = ('apple', 'plepe', 'leoran', 'lemon')
s2 = s1

solution = 'bananaxxxxxxxxxgestrawberryxxxxxxxar'

for word in t:
    if word not in s1: continue
    index = -1 # Start at -1 so our index search starts at 0
    for iteration in range(s1.count(word)):
        index = s1.find(word, index+1)
        length = len(word)
        before = s2[:index]
        after = s2[index+length:]
        s2 = before + 'x'*length + after

print s2 == solution
1 голос
/ 13 ноября 2010

Вот еще один ответ.Возможно, существует более быстрый способ замены букв на x, но я не думаю, что это необходимо, потому что это уже довольно быстро.

import re

def do_xs(s,pats):
    pat = re.compile('('+'|'.join(pats)+')')

    sout = list(s)
    i = 0
    match = pat.search(s)
    while match:
        span = match.span()
        sout[span[0]:span[1]] = ['x']*(span[1]-span[0])
        i = span[0]+1
        match = pat.search(s,i)
    return ''.join(sout)

txt = 'bananaappleorangestrawberryapplepear'
pats = ('apple', 'plepe', 'leoran', 'lemon')
print do_xs(txt,pats)

По сути, я создаю шаблон регулярных выражений, который будет соответствовать любомушаблонов ввода.Затем я продолжаю перезапуск поиска, начиная с 1 после начальной позиции самого последнего совпадения.Может быть проблема, хотя, если у вас есть один из шаблонов ввода, это префикс другого шаблона ввода.

0 голосов
/ 13 ноября 2010
def mask_words(s, words):
    mask = [False] * len(s)
    for word in words:
        pos = 0
        while True:
            idx = s.find(word, pos)
            if idx == -1:
                break

            length = len(word)
            for i in xrange(idx, idx+length):
                mask[i] = True
            pos = idx+length

    # Sanity check:
    assert len(mask) == len(s)

    result = []
    for masked, c in zip(mask, s):
        result.append('x' if masked else c)

    return "".join(result)
0 голосов
/ 13 ноября 2010
a = ('apple', 'plepe', 'leoran', 'lemon')
b = 'bananaappleorangestrawberryapplepear'

for fruit in a:
    if a in b:
        b = b.replace(fruit, numberofx's)

Теперь единственное, что вам нужно сделать, - это определить, сколько Х заменить.

...