【问题标题】:How to find pattern in list of strings, remove it from the string, and insert it as the next element in the list?如何在字符串列表中查找模式,将其从字符串中删除,并将其作为列表中的下一个元素插入?
【发布时间】:2018-04-19 15:52:22
【问题描述】:

我有一个看起来像这样的字符串列表:

list_strings = ["The", "11:2dog", "is", "2:33", "a22:11", "german", "shepherd.2:2"]

这是我想做的:

  1. 对于列表中的每个字符串,我想删除与模式number:number 匹配的数字。此模式将始终位于字符串的开头或结尾。

  2. 当模式从字符串中删除时,如果它在末尾,我想将它作为列表的下一个元素插入,如果它在开头,我想作为列表的前一个元素字符串。

所以:

list_strings = ["The", "11:2dog", "is", "2:33", "a22:11", "german", "shepherd.2:2"]

变成:

new_list_strings = ["The", "11:2", "dog", "is", "2:33", "a", "22:11", "german", "shepherd.", "2:2"]

为了找到可能包含该模式的单词,我尝试使用正则表达式:

for index, word in enumerate(list_strings):
    try:
        if re.search(r'\d+:\d+', word).group() != None:
            words_with_pattern.append([index], word)
    except:
        pass

但是,这只查找模式单独的实例,例如“11:21”。一旦我有了一个包含该模式的所有单词的列表,我将不得不从字符串中删除该模式,注意它是在开头还是结尾,并将其插入到列表中的相应索引处。

有什么帮助吗?谢谢!

【问题讨论】:

    标签: python regex string python-3.x text


    【解决方案1】:

    你可以使用re.split:

    import re
    
    list_strings = ["The", "11:2dog", "is", "2:33", "a22:11", "german", "shepherd.2:2"]
    
    out = []
    
    for item in list_strings:
        split = re.split(r'(\d+:\d+)', item)
        out.extend([part for part in split if part])
    
    print(out)
    # ['The', '11:2', 'dog', 'is', '2:33', 'a', '22:11', 'german', 'shepherd.', '2:2']
    

    split 将包含字符串和分隔符的部分,因为我们在正则表达式中捕获了它。

    如果分隔符位于字符串的末尾/开头,它还包含在分隔符之后/之前的空字符串,因此我们必须在扩展输出之前删除它们。


    正如@chrisz 在 cmets 中建议的那样,这可以使用列表推导以更紧凑的形式编写:

    [j for i in list_strings for j in re.split(r'(\d+:\d+)', i) if j]
    

    【讨论】:

      【解决方案2】:

      此方法使用re.findall 获取字符串中的所有匹配项,然后将结果组合到一个列表中。

      正则表达式\d+:\d+|(?:(?!\d+:\d+).)+ 的工作原理如下:

      • 匹配以下任意一项
        • \d+:\d+ 匹配一位或多位数字,后跟 :,然后是一位或多位数字
        • (?:(?!\d+:\d+).)+ 这是一个tempered greedy token 匹配任何字符一次或多次,除了\d+:\d+ 匹配的位置。这会强制它在该位置停止匹配,并且 findall 方法会重试以匹配该新位置(现在匹配 \d+:\d+ 模式选项,而不是导致每个字符串有多个匹配项)

      方法一

      下面的代码比方法2更容易阅读。

      See code in use here

      import re
      
      ls = ["The", "11:2dog", "is", "2:33", "a22:11", "german", "shepherd.2:2"]
      newls = []
      for s in ls:
          newls += re.findall(r"\d+:\d+|(?:(?!\d+:\d+).)+", s)
      print(newls)
      

      方法二

      这使得方法 1 中的代码单行,但更难阅读。用于扁平化列表sum(l,[])的方法取自this answer

      See code in use here

      import re
      
      ls = ["The", "11:2dog", "is", "2:33", "a22:11", "german", "shepherd.2:2"]
      print(sum([re.findall(r"\d+:\d+|(?:(?!\d+:\d+).)+", s) for s in ls], []))
      

      结果

      ['The', '11:2', 'dog', 'is', '2:33', 'a', '22:11', 'german', 'shepherd.', '2:2']
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-11-17
        • 2019-04-24
        • 1970-01-01
        • 2014-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多