【问题标题】:Pattern match multiple values in a sentence模式匹配句子中的多个值
【发布时间】:2021-01-26 01:34:51
【问题描述】:

我有一个具有特定格式的句子。

<subject> <action> <object> @ <price> ... // The sentence can continue

我想从句子中提取这些值。

约束:

  • 主题始终为BobAlice
  • 操作是boughtsold
  • 对象可以是 1-7 个字母的任何单词 //4apples 应该返回 NULL
  • 价格是浮点数/整数
  • subject之前可以有句子但保证不会 包含Bob/Alice
  • @ 后面可能有也可能没有空格

例子:

Hi there, Bob sold apples @2.0 dollars each

期望的输出:

Subject: Bob
Action: sold
Object: apples
Price: 2.0

目前,我通过以下方式以幼稚的方式做到这一点:

#!/usr/bin/env python3

sentence = "Hi there, alice sold apples @2.0 dollars each"

sentence = sentence.lower()

if 'alice' in sentence or 'bob' in sentence:

    s_list = sentence.split(" ")
    s_idx = -1

    if 'bob' in sentence:
        s_idx = s_list.index('bob')
    elif 'alice' in sentence:
        s_idx = s_list.index('alice')

    if s_idx > -1:
        Subject = s_list[s_idx]
        Action = s_list[s_idx+1]
        Object = s_list[s_idx+2]  #more if/else to validate Object contraints
        Price = s_list[s_idx+3]   #more if/else to extract 2.0 if we get @2.0 

    print("Subject: {}, Action: {}, Object: {}, Price: {}".format(Subject, Action, Object, Price))

我怎样才能做得更好?可能使用re

【问题讨论】:

    标签: python python-3.x regex pattern-matching


    【解决方案1】:

    您可以为每个元素使用带有命名捕获组的正则表达式:

    import re
    
    sentence = "Hi there, alice sold apples @2.0 dollars each"
    
    values = re.search('(?P<subject>bob|alice)\s+(?P<action>bought|sold)\s+(?P<object>[A-Za-z]{1,7})\s+@\s*(?P<price>\d+(?:\.\d+)?)', sentence)
    if values:
        Subject = values['subject']
        Action = values['action']
        Object = values['object']
        Price = values['price']
        print("Subject: {}, Action: {}, Object: {}, Price: {}".format(Subject, Action, Object, Price))   
    

    这将输出

    Subject: alice, Action: sold, Object: apples, Price: 2.0
    

    请注意,您可能需要将re.I 标志提供给re.search 以允许匹配bobBob(或Soldsold 等);在这种情况下,您可以将object 捕获组中的[A-Za-z] 替换为[a-z]

    【讨论】:

    • 谢谢,如果一个不匹配,我们是否能够返回其他值 - 意思是如果 4apples 在句子中有,我们如何仍然返回其他变量?
    • 你可以像这样包装每个捕获组:(?:(?P&lt;subject&gt;bob|alice)|[^\s]+),然后使用类似Subject = values['subject'] or 'not found'的东西
    • 在我上面的评论中,我想要输出:Subject: alice, Action: sold, Object: None, Price: 2.0。除了对象之外,我不需要任何其他值,但知道这是否更复杂仍然很有趣。
    • 保持代码不变,然后将(?P&lt;object&gt;[A-Za-z]{1,7}) 替换为(?:(?P&lt;object&gt;[a-z]{1,7})|[^\s]+)。 rextester 上的演示:rextester.com/SCN47430
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多