【问题标题】:How to wide-space words in a given range in Python?python - 如何在Python中给定范围内的宽词空间?
【发布时间】:2018-07-02 23:59:22
【问题描述】:

给定一个 Python 字符串,我想在给定范围的字符串 sentence 内对给定 word 子字符串的出现进行宽间距。我找不到执行此算法的有效且简洁的方法。

我只想对索引在sentence 字符串的给定范围内的单词进行宽间距,并且单词必须准确(不能被其他单词字符包围,例如字母和数字)。计算单词准确度时会忽略标点符号和其他符号。

到目前为止,我的函数widespace(sentence, word, start = None, end = None): 应该在从startend 的给定范围内对给定的word 进行宽间距,但目前它看起来效率很低且冗长。它也无法检测精确的单词匹配并忽略标点符号。

预期结果

  1. 如果单词在range(start, end) 内,所有出现的单词都会受到影响,也就是说,索引大于或等于start严格小于end
  2. 完全匹配忽略标点符号,但区分大小写。例如,如果要匹配"omg",它接受"omg!""omg,",但不接受被其他单词字符包围的"omg",例如"zomg""omgf"
    • 单词字符可以包括数字、字母、连字符,这是您的偏好。
  3. widespace("Foo, Bar, Baz!", "Baz") 变为 Foo, Bar, B a z!
    • 索引为 10。
  4. widespace("Foo, Foo, Foo!", "Foo") 变为 F o o, F o o, F o o!
    • 索引为 0、5、10。
  5. widespace("Foo, Foo, Foo!", "Foo", start = 0, end = 2) 变为
    F o o, Foo, Foo!
    • 索引为 0、5、10。只有第一个(索引 0)受到影响。
  6. widespace("Foo, Foo, Foo!", "Foo", start = 0, end = 5) 变成
    F o o, Foo, Foo! 就像前面的例子一样
    • 索引为 0、5、10。只有第一个(索引 0)受到影响,因为第二个与 5 完全匹配,超出了范围。
  7. widespace("Foo, Foo, Foo!", "Foo", start = 0, end = 6) 变为
    F o o, F o o, Foo!
    • 索引为 0、5、10。只有前两个得到匹配。
  8. widespace("Mulliganaceous Mulligan, OMG", "Mulligan") 应该变成Mulliganaceous M u l l i g a n, OMG"
    • "Mulliganaceous" 不完全匹配。但是"Mulligan," 算作一个,因为它没有被其他单词字符包围。
    • 我目前有M u l l i g a naceous M u l l i g a n

当前代码

到目前为止,我已经可以使用它了,但是代码很长,可能效率低下,并且无法处理完全匹配和标点符号。

def widespace(sentence: str, word: str, start: int = None, end: int = None):
    if not start:
        start = 0
    if not end:
        end = len(sentence)

    spacedword = " ".join(word)
    indices = []
    cur = sentence.find(word, start)

    # Find all occurrences of the word
    while cur >= 0 and cur < end + len(word) - 1:
        # Add to list
        indices.append(cur) 

        # Next occurrence
        cur = cur + len(word)
        cur = sentence.find(word, cur, end + len(word) - 1)
    print("\t" + str(indices)) # To check indices

    # Replace word with spaced-out word
    while len(indices) > 0:
        index = indices.pop()
        sa = sentence[:index]
        sb = sentence[index:index + len(word)]
        sc = sentence[index + len(word):]
        sb = sb.replace(word, spacedword)
        sentence = sa + sb + sc

    return sentence

如何在 Python 的某个范围内加宽给定单词(完全匹配,忽略标点符号)?满足所有期望的有效解决方案是首选,尽管我对结果非常灵活。

【问题讨论】:

  • 您的第二个示例的结束范围应该是 5 而不是 4?
  • 谢谢我的坏。我只是在编辑问题以使其更清楚。

标签: python string whitespace


【解决方案1】:

首先,“宽空间”整个字符串的最简单,可能也是最有效的方法是:

' '.join(s)

这是因为字符串是迭代每个单独字符的可迭代对象,因此如果您将一个传递给join,它会将所有字符与每对之间的分隔符连接起来。

那么,如何处理字符串的widespace 部分?很简单:把它切开,join 只是你想要加宽的部分,然后将它合并在一起:

s[:start] + ' '.join(s[start:end]) + s[end:]

这与您要求的界面不太一样,但是我不确定word 在您的问题中应该做什么,所以我只写了最简单的东西,即widespaces 一切 em>,希望你能弄清楚如何将它映射到你想要的:

>>> s = 'foo foo foo foo foo foo foo'
>>> s[:8] + ' '.join(s[8:15]) + s[15:]
'foo foo f o o   f o o foo foo foo'

请注意,这也允许您使用start=None, end=None 默认值,它们将自动使用与切片、range 等相同的含义:None 表示从开头开始或结尾在结束。

这将非常有效,但可能不如创建自定义 C 扩展(在开始时为 len(s) + end - start 保留空间然后循环遍历 C 中的字符)高效。

【讨论】:

  • 你能举一些例子来说明你的算法是如何工作的以及它是如何达到预期的吗?
  • @Oighea 已编辑。但是,正如我所说,我不明白你的期望是如何运作的。例如,如果foo 的一半在范围内,会发生什么情况?你是把整个东西都加宽,只是范围内的一半,还是两者都不加?不管答案是什么,你应该可以很容易地解决它:首先将字符串分成前、中和后部分,然后只在中间进行替换,然后将它们重新加在一起。
  • 你把整个事情都放宽了。为进一步清晰而进行了编辑。
  • 我添加了关于word 定义的附加说明。在这里,word 只是要匹配的子字符串。此外,单词的“精确匹配”是不被单词字符包围的单词。匹配 "OMG" 时,"OMG," 计数,但不匹配 "zOMG""OMG!"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
  • 1970-01-01
  • 2021-02-11
  • 1970-01-01
  • 2020-03-12
  • 2021-05-05
  • 2016-07-15
相关资源
最近更新 更多