【问题标题】:Is there a more Pythonic way to iterate through dictionary keys looking for a value than this?有没有比这更 Pythonic 的方式来遍历字典键以查找值?
【发布时间】:2018-07-03 04:07:19
【问题描述】:

这是一个示例字典,colors

{
    "Red" : {
        "members" : {
            "153950039532134112" : {
                "rank" : 1,
                "score" : 43,
                "time" : 1530513303
            }
        },
        "rank" : 2,
        "score" : 43
    },
    "Blue" : {
        "members" : {
            "273493248051539968" : {
                "rank" : 1,
                "score" : 849,
                "time" : 1530514923
            },
            "277645262486011904" : {
                "rank" : 2,
                "score" : 312,
                "time" : 1530513964
            },
            "281784064714487810" : {
                "rank" : 3,
                "score" : 235,
                "time" : 1530514147
            }
        },
        "rank" : 1,
        "score" : 1396
    }
}

为了这个例子,让我们假设这个字典中有更多的颜色命名键。现在,假设我正在寻找一个特定的会员 ID。

for key, value in colors.items():
    if member_id in value['members']:
        return True

有没有更简单的,可能是单行的方法来做到这一点?

【问题讨论】:

  • 您期待一个结果吗?还是存在 member_id 的颜色列表?
  • 那么你不需要colors[key],因为这只是value,所以它相当于if member_id in value['members']。但这是一件小事,因为索引到 dictO(1) 操作。

标签: python python-2.7 dictionary


【解决方案1】:

这是另一个使用any 加上一个 generator expression:

return any(member_id in color['members'] for color in colors.values())

【讨论】:

  • @skrx TIL 列表推导和生成器表达式之间的区别。 This link 将有助于解释答案中的单行迭代。我不是故意添加不正确的信息。鉴于批准的数量,我认为这是一个很好的编辑。
【解决方案2】:

您可以使用list comprehension,这只是执行 for 循环和条件语句的一种简洁方式。

member_id 存在时,下面的列表解析将返回一个颜色值。如果您检查返回的列表是否至少有一个值,则您知道member_id 至少存在于一个颜色字典中。如果您制作两行并分配输出,您还可以方便地使用颜色字典,以防您需要修改或读取其任何状态。

any([color for color in colorDict if member_id in colorDict[color]['members']])

我会说这比您问题中的示例更 Pythonic,但是当涉及更多复杂性时,有时列表推导可能不清楚。例如,如果您需要两个循环和两个条件,那么列表推导式可能不是最佳选择。总的来说,它们是一个非常有用的工具,但您可以决定何时使用它们。

【讨论】:

  • 我认为这行不通。也许你的意思是... in colorDict[color]['members']?你的方括号也不平衡。
【解决方案3】:

这是一种单行的方法:

member_id="273493248051539968"

[k for k, v in colors.items() if member_id in v['members']]

输出:

['Blue']

【讨论】:

  • 这似乎不必要地复杂,因为你知道它在 v['members'] 中,所以 [k for k, v in colors.items() if member_id in v['members']] 会做同样的事情,假设 OP 不是简单地寻找 True / False返回。
  • 这将输出包含该 member_id 的 所有 键的列表。如果这是您想要的,那很好,但这也意味着它必须搜索整个字典并且不会捷径,这与问题中的长解决方案不同,这很糟糕,因为 colors 应该是一个大字典,并且如果成员 ID 每个只出现一次,那么额外的工作是没有用的。
【解决方案4】:
next((k for k, v in colors.items() if member_id in v['members']), None)

使用member_id 评估第一个颜色键,如'Blue'(或None,如果未找到)。

生成器表达式是惰性的,因此一旦找到匹配项就会停止搜索。

【讨论】:

  • 这是一个奇怪的公式,一点也不像 Python。它也不比使用生成器的any 更有效,这是一个现有的答案。
  • @MatthewStory 不,不会的,试试看。 next 函数采用一个额外的默认参数,它抑制 StopIteration 行为。与any 不同,它可以找到第一个键。
  • 哦,太好了,我不知道 next 的额外参数。仍然很奇怪,并且没有比 any 使用生成器更有效。
猜你喜欢
  • 2011-05-04
  • 1970-01-01
  • 2019-09-30
  • 1970-01-01
  • 2021-11-12
  • 2018-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多