【问题标题】:How do I filter out expressions from a line of text using Python?如何使用 Python 从一行文本中过滤掉表达式?
【发布时间】:2017-12-22 19:52:40
【问题描述】:

我想删除不属于预定义列表的单词。例如,如果我的列表是:

ANIMAL
BIRD
CARNIVORE
HERBIVORE
MAMMAL
OMNIVORE

我的输入是这样的:

(ANIMAL (CARNIVORE (BIRD Peacock)) (HERBIVORE (MAMMAL Goat)))

我希望我的输出是:

(ANIMAL (CARNIVORE (BIRD )) (HERBIVORE (MAMMAL )))

我试过了:

current_split = re.split("\W", test)
    for thing in current_split:
        if thing in parse_symbols:
            print thing

但这删除了括号,我得到了这个:

ANIMAL
CARNIVORE
BIRD
HERBIVORE
MAMMAL

另外,由于 for 循环,引入了换行符,这是我不想要的。

我做错了什么?

【问题讨论】:

  • 您的输入是否总是带有要保留的括号?那么唯一需要删除的是额外的字母字符串?
  • 您想在打印后添加“,”并在上一级添加换行符
  • @mattjegan 是的。

标签: python regex string text


【解决方案1】:

使用重新子:

bird = re.compiler'(BIRD) (\w*?)\)'
mammal = re.compile(r'(MAMMAL) (\w*?)\)')

nobirds  = re.sub(bird, r'\1', input) #keeps only the first group
nomammals = re.sub(mammal, r'\1', input)

【讨论】:

    【解决方案2】:

    使用re.finditer()函数的解决方案:

    import re
    
    animals = ['ANIMAL', 'BIRD', 'CARNIVORE', 'HERBIVORE', 'MAMMAL', 'OMNIVORE']
    user_input = '(ANIMAL (CARNIVORE (BIRD Peacock)) (HERBIVORE (MAMMAL Goat)))'
    
    for m in re.finditer(r'[\w-]+', user_input):
        if m.group() not in animals:
            user_input = user_input.replace(m.group(), '')
    
    print(user_input)
    

    输出:

    (ANIMAL (CARNIVORE (BIRD )) (HERBIVORE (MAMMAL )))
    

    【讨论】:

    • 不,您可以删除任何单词的前缀
    • @AnttiHaapala,前缀是什么意思?不清楚你在写什么
    • 您的代码会找到不在user_input 中的每个单词,并在任何地方替换为'',即使它们是另一个单词的一部分。
    【解决方案3】:

    如果您只打算处理与您提供的带有括号的字符串类似的字符串,您可以将split 行变成单词,strip 括号,然后检查它们是否允许:

    allowed = ['ANIMAL', 'BIRD', 'CARNIVORE', 'HERBIVORE', 'MAMMAL', 'OMNIVORE']
    line = '(ANIMAL (CARNIVORE (BIRD Peacock)) (HERBIVORE (MAMMAL Goat)))'
    words = [word.strip('()') for word in line.split()]
    not_allowed = [word for word in words if word not in allowed]
    

    现在我们找到了所有要删除的单词,我们只需将它们删除,如下所示:

    newline = line
    for word in not_allowed:
        newline = newline.replace(word, '')
    

    newline 现在唯一的问题是括号前那些烦人的空格,我们删除了单词,但这很容易:

    newline = newline.replace(' )', ')')
    

    你的换行符现在应该输出'(ANIMAL (CARNIVORE (BIRD)) (HERBIVORE (MAMMAL)))'

    另外,如您所见,我在此会话期间没有打印每个单词,这就是为什么我现在可以打印一行 newline,而不是在每个 print 命令上打印多个新行

    【讨论】:

      【解决方案4】:

      这是万无一失的解决方案:将re.sub 与函数一起使用。首先获取允许单词的set

      allowed = set("""
          ANIMAL
          BIRD
          CARNIVORE
          HERBIVORE
          MAMMAL
          OMNIVORE
      """.split())
      

      或使用

      allowed = {'ANIMAL', 'BIRD', #... and so forth
      

      然后re.sub 为每个单词\w+ 加上一个正则表达式,然后检查它们是否在ok - 如果是,则返回该单词,否则返回一个空字符串:

      def replacement(match):
          word = match.group(0)
          if word in allowed:
              return word
          return ''
      
      result = re.sub(r'[\w-]+', replacement, user_input)
      print(result)
      

      打印

      (ANIMAL (CARNIVORE (BIRD )) (HERBIVORE (MAMMAL )))
      

      这将只考虑整个单词和整个单词,这与此处提供的各种.replace 解决方案不同。如果整个单词都在允许的单词集中,它只会保留一个单词。它永远不会删除完整单词的一部分。它适用于任何分隔符和运算符。

      如果您想删除右括号前的多余空格,请使用另一个替换:

      re.sub(r'\s+\)', '', result)
      

      上面的结果会产生什么

      (ANIMAL (CARNIVORE (BIRD) (HERBIVORE (MAMMAL))
      

      【讨论】:

      • 你不应该在你的replacement函数中使用allowed而不是ok吗?
      • @RomanPerekhrest 非常感谢。这就是片段编码然后重写变量名的问题
      • @AnttiHaapala 这行得通,但是对于像 (ANIMAL (CARNIVORE (BIRD jay-bird))) 这样的情况,连字符被保留。我该如何摆脱它?
      • @user110327 通过使用包含任何单词字符的字符类-。即[\w-]+
      • @user110327 我已经修复了上面的代码来处理这个案例
      猜你喜欢
      • 2011-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多