Мне нужно разбить строку на слова, но также получить начальное и конечное смещение слов. Так, например, если входная строка:
input_string = "ONE ONE ONE \t TWO TWO ONE TWO TWO THREE"
Я хочу получить:
[('ONE', 0, 2), ('ONE', 5, 7), ('ONE', 9, 11), ('TWO', 17, 19), ('TWO', 21, 23),
('ONE', 25, 27), ('TWO', 29, 31), ('TWO', 33, 35), ('THREE', 37, 41)]
У меня есть рабочий код, который делает это с помощью input_string.split и вызывает .index, но он медленный. Я попытался закодировать его, выполнив русскую итерацию по строке, но это было медленнее. У кого-нибудь есть быстрый алгоритм для этого?
Вот мои две версии:
def using_split(line):
words = line.split()
offsets = []
running_offset = 0
for word in words:
word_offset = line.index(word, running_offset)
word_len = len(word)
running_offset = word_offset + word_len
offsets.append((word, word_offset, running_offset - 1))
return offsets
def manual_iteration(line):
start = 0
offsets = []
word = ''
for off, char in enumerate(line + ' '):
if char in ' \t\r\n':
if off > start:
offsets.append((word, start, off - 1))
start = off + 1
word = ''
else:
word += char
return offsets
Используя timeit, "using_split" является самым быстрым, за которым следует "manual_iteration", то самым медленным до сих пор является использование re.finditer, как предлагается ниже.