避免重复if语句

2024-05-15 04:48:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我为此任务准备了函数和排序数据: (这实际上是AoC第4天,但需要快速解释清楚) 我已经将数据排序到此“结构”中

byr:1991
eyr:2022
hcl:#341e13
iyr:2016
pid:729933757
hgt:167cm
ecl:gry

hcl:231d64
cid:124
ecl:gmt
eyr:2039
hgt:189in
pid:#9c3ea1

ecl:#1f58f9
pid:#758e59
iyr:2022
hcl:z
byr:2016
hgt:68
eyr:1933

[以此类推+250个包(我所说的包是指一组byr、ecl、eyr……用新行分隔)。]

并编写了此代码:

def check_fields(list):
    comparison_list = ['byr', 'iyr', 'eyr',
                       'hgt', 'hcl', 'ecl',
                       'pid']
    statement = True
    for i in comparison_list:
        statement = statement and (i in list)
    return statement


def check_byr_iyr_eyr(line):
    prefix,value = line.split(':')
    cases = {'byr':{'min':1920, 'max':2002},
             'iyr':{'min':2010, 'max':2020},
             'eyr':{'min':2020, 'max':2030} }
    return cases[prefix]['min'] <= int(value) <= cases[prefix]['max']


def check_hgt(line):
    unit = line[len(line)-2] + line[len(line)-1]
    value = line[line.index(':')+1: -2]
    cases = {'cm':{'min':150, 'max':193},
             'in':{'min':59, 'max':76}}
    return cases[unit]['min'] <= int(value) <= cases[unit]['max']


def check_hcl(line):
    statement = True
    if line[line.index(':')+1] != '#' or len(line[line.index(':')+2:]) != 6:
        return False
    else:
        string = line[line.index('#')+1:]
        for i in string:
            statement = statement and (97 <= ord(i) <= 102 or 48 <= ord(i) <= 57)
        return statement


def check_ecl(line):
    comparison_list = ['amb', 'blu', 'brn',
                       'gry', 'grn', 'hzl',
                       'oth' ]
    if line[line.index(':') + 1:] in comparison_list:
        return True
    return False


def check_pid(line):
    if len(line[line.index(':')+1:]) != 9:
        return False
    try:
        int(line[line.index(':')+1:])
        return True
    except:
        return False


line_list = []
valid_passports = 0
with open('results.txt', 'r') as f:
    for line in f:
        if line != '\n':
            ''' add line to line_list'''
            pass
        else:
            '''
            check lines from line_list
            using above declared functions
            if every line is ok:
                valid_passports +=1
            '''

我必须检查每个包是否包含除cid之外的所有键,然后检查每个键的每个值是否正确

byr (Birth Year) - four digits; at least 1920 and at most 2002.
iyr (Issue Year) - four digits; at least 2010 and at most 2020.
eyr (Expiration Year) - four digits; at least 2020 and at most 2030.
hgt (Height) - a number followed by either cm or in:
If cm, the number must be at least 150 and at most 193.
If in, the number must be at least 59 and at most 76.
hcl (Hair Color) - a # followed by exactly six characters 0-9 or a-f.
ecl (Eye Color) - exactly one of: amb blu brn gry grn hzl oth.
pid (Passport ID) - a nine-digit number, including leading zeroes.
cid (Country ID) - ignored, missing or not. 

(上述规则由先前声明的函数保证)
问题是,在检查添加到行列表中的每一行时,如何避免重复if语句(它指带有“伪代码”的多行注释的部分)我的意思是我可以像这样做

if line[0:3] == "byr":
    check_byr(line)
# and so on, many if statement checking the first 3 letters to adjust proper function to use

但这似乎不是一个恰当而优雅的解决方案,matybe你可以给我一些如何处理这个问题的提示,或者给我另一个想法,用我没有用过的不同方式来解决这个问题。 请帮忙,谢谢


Tags: andinindexreturnifchecklinemin
3条回答

你不能有一个从前缀到目标函数的映射吗

差不多

line = # ...
prefix = # ... either "hgt" or "pid" or other

def check_hgt(line):
    pass
def check_pid(line):
    pass
# ... other checker functions

checker_functions_pool = {"hgt": check_hgt, "pid": check_pid}

checker_function = checker_functions_pool[prefix]
checker_function(line)

@viGor207,这是另一种方法:(第二部分示例):

import re

passports = [
    dict(
        line.split(':')
        for line
        in pas.split()
    )
    for pas
    in open('input').read().split('\n\n')
]

required = {'byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid'}


def valid(pas):
    return bool(
        1920 <= int(pas['byr']) <= 2002 and
        2010 <= int(pas['iyr']) <= 2020 <= int(pas['eyr']) <= 2030 and
        re.fullmatch(r'[0-9]{2,3}(cm|in)', pas['hgt']) and
        (
            (pas['hgt'][-2:] == 'cm' and 150 <= int(pas['hgt'][:-2]) <= 193) or
            (pas['hgt'][-2:] == 'in' and 59 <= int(pas['hgt'][:-2]) <= 79)
        ) and
        re.fullmatch(r'#[0-9a-f]{6}', pas['hcl']) and
        pas['ecl'] in {'amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth'} and
        re.fullmatch(r'[0-9]{9}', pas['pid'])
    )


print(
    sum(
        all(r in pas for r in required) and valid(pas)
        for pas
        in passports
    )
)

为使其完整,以下是第一部分:

passports = [
    dict(
        line.split(':')
        for line
        in pas.split()
    )
    for pas
    in open('input').read().split('\n\n')
]

required = {'byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid'}

print(
    sum(
        all(r in pas for r in required)
        for pas in passports
    )
)

相关问题 更多 >

    热门问题