【问题标题】:Dividing a string at various punctuation marks using split()使用 split() 在各种标点符号处划分字符串
【发布时间】:2012-04-05 13:02:09
【问题描述】:

我正在尝试将字符串分成单词,删除空格和标点符号。

我尝试使用split() 方法,一次传递所有标点符号,但结果不正确:

>>> test='hello,how are you?I am fine,thank you. And you?'
>>> test.split(' ,.?')
['hello,how are you?I am fine,thank you. And you?']

我实际上已经知道如何使用正则表达式来做到这一点,但我想弄清楚如何使用split() 来做到这一点。请不要给我正则表达式解决方案。

【问题讨论】:

  • 所以你坚持用扳手打钉子,而锤子就在手边。为什么?
  • 没有任何不尊重 OP 的意思,我认为应该为这类问题贴上标签,在这些问题中,无论出于何种原因(有时是有效的),适当的工具都会被冷落,它们不时出现。也许luddism
  • 试试 C# "你好,你好吗?我很好,谢谢。你呢?".Split(",? .".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
  • 不要让任何人阻止您探索非正则表达式方法来进行简单的文本操作。使用字符串方法、itertools.groupby 和实际编写函数(!),我们中的一些人几乎从不使用正则表达式,并且为了换取更多的击键,我们可以编写出漂亮、干净、易于调试的 Python .

标签: python string split


【解决方案1】:

你可以写一个函数来扩展.split()的使用:

def multi_split(s, seprators):
    buf = [s]
    for sep in seprators:
        for loop, text in enumerate(buf):
            buf[loop:loop+1] = [i for i in text.split(sep) if i]
    return buf

试试看:

>>> multi_split('hello,how are you?I am fine,thank you. And you?', ' ,.?') ['hello', 'how', 'are', 'you', 'I', 'am', 'fine', 'thank', 'you', 'And', 'you']

这样会更清晰,可以在其他情况下使用。

【讨论】:

    【解决方案2】:

    保留标点符号或其他分隔符的简单方法是:

    import re
    
    test='hello,how are you?I am fine,thank you. And you?'
    
    re.findall('[^.?,]+.?', test)
    

    结果:

    ['hello,', 'how are you?', 'I am fine,', 'thank you.', ' And you?']
    

    也许这可以帮助某人。

    【讨论】:

      【解决方案3】:

      为 necroing 道歉 - 此线程是非正则表达式拆分句子的第一个结果。看到我必须为我的学生想出一个非 Python 特定的方法,并且这个线程没有回答我的问题,我想我会分享以防万一。

      代码的重点是不使用库(而且它在大文件上很快):

      sentence = "George Bernard-Shaw was a fine chap, I'm sure - who can really say?"
      alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
      words = []
      word = ""
      mode = 0
      for ch in sentence:
          if mode == 1:
              words.append(word)
              word = ""
              mode = 0
          if ch in alpha or ch == "'" or ch == "-":
              word += ch
          else:
              mode = 1
      words.append(word)
      print(words)
      

      输出:

      ['George', 'Bernard-Shaw', 'was', 'a', 'fine', 'chap', "I'm", 'sure', '-', 'who', 'can', 'really', 'say']
      

      我在大约半小时内才写完这篇文章,所以我确信逻辑可以被清理掉。我还承认,正确处理连字符等警告可能需要额外的逻辑,因为与倒逗号之类的东西相比,它们的使用不一致。确实有任何模块可以正确执行此操作吗?

      【讨论】:

        【解决方案4】:

        larsks 答案的修改版本,您无需自己输入所有标点符号:

        import re, string
        
        re.split("[" + string.punctuation + "]+", test)
        ['hello', 'how are you', 'I am fine', 'thank you', ' And you', '']
        

        【讨论】:

          【解决方案5】:

          既然你不想使用 re 模块,你可以使用这个:

           test.replace(',',' ').replace('.',' ').replace('?',' ').split()
          

          【讨论】:

          • test='你好,你好吗?我很好,谢谢。和你?' for x in test: if not x.isalpha():test=test.replace(x,' ') test=test.split() print test
          【解决方案6】:

          这是我能想到的最好的不使用 re 模块的方法:

          "".join((char if char.isalpha() else " ") for char in test).split()
          

          【讨论】:

          • 哦,这是另一种方法,虽然它不使用拆分字符的显式列表...
          • 这很棒。虽然,与使用 re.split 相比,它的效率要低一些。
          【解决方案7】:

          如果您想根据 多个 分隔符拆分字符串,就像在您的示例中一样,您将需要使用 re 模块,尽管您有奇怪的反对意见,如下所示:

          >>> re.split('[?.,]', test)
          ['hello', 'how are you', 'I am fine', 'thank you', ' And you', '']
          

          有可能使用split 得到类似的结果,但是您需要为每个字符调用一次 split,并且您需要遍历前一个 split 的结果。这可行,但它是u-g-l-y:

          >>> sum([z.split() 
          ... for z in sum([y.split('?') 
          ... for y in sum([x.split('.') 
          ... for x in test.split(',')],[])], [])], [])
          ['hello', 'how', 'are', 'you', 'I', 'am', 'fine', 'thank', 'you', 'And', 'you']
          

          这使用sum() 来展平上一次迭代返回的列表。

          【讨论】:

          • 请不要使用sum() 来扁平化列表列表 -- it's the wrong tool for this purpose。在这种特殊情况下更是如此,因为single list comprehension using a nested loop 将首先消除展平的必要性。
          • 如果您认为它更适合该问题,我们非常欢迎您发布替代解决方案。
          • 只要 OP 没有解释为什么不应该使用 re,我就不会发布答案,因为我还不明白这个问题的目的。不过,我上一条评论中的第二个链接显示了另一种解决方案。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-06-03
          • 2012-01-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多