1

我知道解决这个解决方案有 1001 种方法,我要求社区了解最 Pythonic 的方法似乎是什么。

假设我有一个采用以下格式的字典列表:

colours = [{"color": "green", "owner": "Mark"},
           {"color": "blue", "owner": "Luke"},
           {"color": "red", "owner": "John"}]

忽略列表应该是字典字典的明显事实,我想从列表中检索单个字典给定用户输入color字典中的键,但如果颜色不匹配则使用默认值(让在这个例子中说“绿色”)。

因此,我正在寻找一个功能:

def get_with_default(colour, colours, default):

给定颜色列表将返回:

>>> get_with_default("blue", colours, "green") # Valid dictionary
{"color": "blue", "owner": "Luke"}
>>> get_with_default("black", colours, "green") # Colour doesn't exist
{"color": "green", "owner": "Mark"}

更新(感谢 Martijn),默认值将被硬编码并且已知在列表中,但是该字典中的其他键/值对是未知/动态的(所以我知道“绿色”是字典中的键,但我知道在这个简化的案例中谁“拥有”绿色

4

3 回答 3

4

next()是实现这一目标的最 Pythonic 函数:

def get_with_default(colour, colours, default):
    search = (d for d in colours if d['color'] in (colour, default))
    match_or_default = next(search)
    if match_or_default['color'] != default or default == colour:
        return match_or_default
    return next(search, match_or_default)

next()循环第一个参数,直到产生结果,然后返回。如果第一个参数用尽,StopIteration则改为引发,除非给出第二个参数,否则为默认值,在这种情况下返回该值而不是引发异常。

通过给它一个包含搜索的生成器表达式,您可以有效地扫描colours列表以查找第一个匹配项。如果这是默认设置,那么我们将继续扫描,直到找到另一个匹配项,或者到达列表的末尾。

演示:

>>> get_with_default("blue", colours, "green")
{'color': 'blue', 'owner': 'Luke'}
>>> get_with_default("black", colours, "green")
{'color': 'green', 'owner': 'Mark'}

上面的方法非常有效,因为它只需要扫描输入列表一次,一旦找到匹配就停止扫描。

请注意,StopIteration如果默认值不存在,则此函数将引发:

>>> get_with_default("black", colours, "purple")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in get_with_default
StopIteration

None在这种情况下,您也可以通过为第一次next()调用提供默认返回值来返回:

match_or_default = next(search, None)
于 2013-07-22T11:43:58.397 回答
2

不是最好的,但很好且可读:

def get_with_default(colour, L, default=''):
    temp = None
    for d in L:
        if d['color'] == colour:
            return d
        elif d['color'] == default:
            temp = d
    return temp

测试时:

>>> get_with_default('blue', colours, 'green')
{'color': 'blue', 'owner': 'Luke'}
>>> get_with_default('black', colours, 'green')
{'color': 'green', 'owner': 'Mark'}
于 2013-07-22T11:54:33.637 回答
0

您也可以使用列表推导来实现这一点。

def get_with_defaults(color,colours,default='green'):
    res = [col for col in colours if col['color']==color]   
    if not res:
        return [col for col in colours if col['color']==default]
    return res

get_with_defaults('blue',colours)
[{'color': 'blue', 'owner': 'Luke'}]
>>> get_with_defaults('black',colours)
[{'color': 'green', 'owner': 'Mark'}]

在字典中输出。

def get_with_defaults(color,colours,default='green'):
    res = [col for col in colours if col['color']==color]   
    if not res:
        return [col for col in colours if col['color']==default][0]
    return res[0]

get_with_defaults('blue',colours)
{'color': 'blue', 'owner': 'Luke'}
>>> get_with_defaults('black',colours)
{'color': 'green', 'owner': 'Mark'}
于 2013-07-22T12:20:23.310 回答