re.search()如果结果为None

时间:2016-10-03 16:04:22

标签: python

如何制作这种pythonic?

def money_from_string(s):
    gold = re.search("([0-9]+)g", s)
    silver = re.search("([0-9]+)s", s)
    copper = re.search("([0-9]+)c", s)
    s = re.sub("[0-9]+g", "", s)
    s = re.sub("[0-9]+s", "", s)
    s = re.sub("[0-9]+c", "", s)
    assert (len(s.strip()) == 0) # should be 0

    return (gold.group() or 0) * 10000 + (silver.group() or 0) * 100 + (copper.group() or 0)

这不起作用,因为如果goldNone,则gold.group()会引发错误。

输入示例&预期产出:

s = "15g17s5c" -> 150000 + 1700 + 5 -> 151705
s = "15g5s"    -> 150000 + 500      -> 150500
s = "15g"      -> 150000            -> 150000
s = "17s5c"    -> 1700 + 5          -> 1705
s = "5c"       -> 5                 -> 5

请注意,我会对输入进行适当的检查,以确保其格式正确。 IE浏览器。它匹配:

MONEY_PATTERNS = [
    "([0-9]+g[ ]*[0-9]+s[ ]*[0-9]+c)", # g / s / c
    "([0-9]+g[ ]*[0-9]+s)", # g / s
    "([0-9]+g[ ]*[0-9]+c)", # g / c
    "([0-9]+s[ ]*[0-9]+c)", # s / c
    "([0-9]+g)", # g
    "([0-9]+s)", # s
    "([0-9]+c)", # c
]

2 个答案:

答案 0 :(得分:1)

以下是我如何实施您的计划。

注意:

  • 您必须使用int()将字符串转换为整数
  • 我会将验证与计算分开,但在两种情况下都使用相同的正则表达式。
  • 我会用字典而不是代码来保存金属的价值。
  • 通过使用金属的字符类,我只需要调用re.findall()一次。
  • 我的正则表达式允许更丰富的库存字符串,例如"10g 10g 10g"代表30个金币。

import re

money_from_string_pattern = re.compile(r"(\d+)([gsc])")


def is_money_from_string_valid(s):
    return not money_from_string_pattern.sub("", s).strip()


def money_from_string(s):
    value = {'g': 10000, 's': 100, 'c': 1}
    inventory = money_from_string_pattern.findall(s)
    return sum(int(amount) * value[metal] for amount, metal in inventory)

assert money_from_string("11g 22s 33c") == 112233
assert money_from_string("11g") == 110000
assert money_from_string("11g 11g") == 220000

assert is_money_from_string_valid("11g 22s 33c") == True
assert is_money_from_string_valid("11g") == True
assert is_money_from_string_valid("11g 11g") == True

assert is_money_from_string_valid("11 g 22s 33c") == False
assert is_money_from_string_valid("11g 22q") == False
assert is_money_from_string_valid("stackoverflow.com") == False

答案 1 :(得分:-1)

如果返回的值为None,则只需检查无,并将其替换为0。这似乎与你想要做的事情相符。

def money_from_string(s):
    gold = re.search("([0-9]+)g", s)
    silver = re.search("([0-9]+)s", s)
    copper = re.search("([0-9]+)c", s)
    if str(gold) in 'None':
        gold = 0
    if str(silver) in 'None':
        silver = 0
    if str(copper) in 'None':
        copper = 0
    s = re.sub("[0-9]+g", "", s)
    s = re.sub("[0-9]+s", "", s)
    s = re.sub("[0-9]+c", "", s)
    assert (len(s.strip()) == 0) # should be 0

    return ((gold.group() * 10000 + silver.group() * 100 + copper.group())