2017-07-18 16 views
2

我想删除不属于预定义列表的单词。例如,如果我的名单是:如何从一行文本中使用Python过滤表达式?

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循环,越来越推出新行,这是我不想要的。

我在做什么错?

+1

是您输入总是有括号你想保持?所以需要删除的唯一东西是额外的字母字符串? – mattjegan

+1

你想添加一个“,”打印后,并添加一个级别以上的换行 –

+0

@mattjegan是的。 – user110327

回答

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)) 
+0

不应该在你的'replacement'函数中使用'allowed'而不是'ok'? – RomanPerekhrest

+0

@RomanPerekhrest真的谢谢。这是编写碎片然后重写变量名称的问题 –

+0

@AnttiHaapala这可行,但对于像(ANIMAL(CARNIVORE(BIRD jay-bird)))的情况,连字符被保留。我如何摆脱它? – user110327

0

使用重子:

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))) 
+0

不,您可以删除任何单词的*前缀*。 –

+0

@AnttiHaapala,你用*前缀*表示什么?不清楚你在写什么 – RomanPerekhrest

+0

你的代码发现每个单词都不在'user_input'中,并且在任何地方都会用'''替换,即使它们是另一个单词的一部分。 –

0

如果你只打算来处理类似一个字符串你提供了括号,你可以只用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命令

相关问题