用单词索引替换字符串字符

时间:2019-02-23 18:48:14

标签: python-3.x string nlp

请注意该字符串中两个连续的空格:

string = "Hello there  everyone!"

for i, c in enumerate(string):
    print(i, c)

 0 H
 1 e
 2 l
 3 l
 4 o
 5
 6 t
 7 h
 8 e
 9 r
10 e
11
12
13 e
14 v
15 e
16 r
17 y
18 o
19 n
20 e
21 !

如何使列表len(string)长,每个值包含的字数一直到字符串中的该点?

预期输出:0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2

我唯一的方法是循环遍历每个字符,设置space=True标志,并在每次space == True遇到非空格字符时增加一个计数器。这可能是因为我最精通C语言,但是我想学习一种更Python化的方法来解决此问题。

1 个答案:

答案 0 :(得分:1)

我觉得您的解决方案与pythonic差不多。也许您可以使用zip运算符将字符串二乘二迭代,然后检测局部变化(从空格到字母->这是一个新词):

string = "Hello there  everyone!"

def word_index(phrase):
  nb_words = 0
  for a, b in zip(phrase, phrase[1:]):
    if a == " " and b != " ":
      nb_words += 1
    yield nb_words

print(list(word_index(string)))

这也利用了generators,这在python中很常见(请参阅yield keyword的文档)。您可以使用itertools.accumulate而不是for循环来执行相同的操作,但是我不确定它不会混淆代码(请参见The Zen of Python的第三项)。这就是它的样子,请注意,我在这里使用了lambda函数,不是因为我认为这是最佳选择,而是因为我找不到任何有意义的函数名:

import itertools

def word_index(phrase):
  char_pairs = zip(phrase, phrase[1:])
  new_words = map(lambda p: int(p[0] == " " and p[1] != " "), char_pairs)
  return itertools.accumulate(new_words)

第二个版本类似于第一个版本,返回iterator。请注意,使用迭代器通常是一个好主意,因为它不会对用户是否要实例化任何内容做出任何假设。如果用户想将迭代器it转换为列表,他可以像在第一段代码中一样始终调用list(it)。迭代器只是简单地为您提供值:在任何时间点,内存中只有一个值:

for word_index in word_index(string):
    print(word_index)

请注意,phrase[1:]对短语进行了复制,这意味着它将使使用的内存增加一倍。可以通过使用返回迭代器的itertools.islice进行改进(因此仅使用常量内存)。例如,第二个版本如下所示:

def word_index(phrase):
  char_pairs = zip(phrase, itertools.islice(phrase, 1, None))
  new_words = map(lambda p: int(p[0] == " " and p[1] != " "), char_pairs)
  return itertools.accumulate(new_words)