【问题标题】:function that looks up keys in a dictionary until there is no more associated values在字典中查找键直到没有更多关联值的函数
【发布时间】:2019-12-23 04:29:49
【问题描述】:

我需要帮助创建一个通过给定字典的函数。与该键关联的值可能是字典的另一个键。我需要这个函数来继续查找键,直到它到达一个没有关联值的键。

def follow_me(d, s):

    while d:
        if s in d:
            return d[s]

我可以返回字典中 s 等于的值,但我不知道如何迭代它,直到我得到一个没有关联值的值。所以我可以得到 badger 是 doe 的值,但是我如何遍历字典直到我得到 fox 然后 fox to hen 等。

d = {'badger':'doe', 'doe':'fox', 'fox':'hen','hen':'flea',
'sparrow':'spider', 'zebra':'lion', 'lion':'zebra'}
print(follow_me(d, 'badger'))
print(follow_me(d, 'fox'))
print(follow_me(d, 'sparrow'))
print(follow_me(d, 'zebra'))
print(follow_me(d, 'aardvark'))

这就是我目前拥有的对我有意义的功能,因为我尝试过的其他一切都是错误的。

def follow_me(d, s):
    while d:
        if s in d:
            return d[s]

输出需要是:

flea
flea
spider
aardvark

但我的代码现在正在生成:

doe
hen
spider
lion

【问题讨论】:

  • 这种情况下保证不会发生
  • @Moormanly:在他们的例子中,'lion''zebra'。我不确定他们希望它做什么。
  • 哦,狮子和斑马他们希望它被打印为假,但我还没有满足例外情况,因为我不知道如何迭代它
  • 我很确定您的代码不会打印aardvark。当您进行最后一次示例调用时,您显示的函数将永远运行。
  • 在您给出的示例代码中,如果d 是非空字典,则while d: 等价于while True:,如果d 是空字典,则while False: 等价于while False:。这些都不是你想要的。您可以尝试while s in d: 并在循环内更新s

标签: python python-3.7


【解决方案1】:

扩展其他仍然有效的答案。如果您有一个 非常 大的字典,那么使用 key not in dic.keys()k in d 会在每个循环中遍历所有键。

要解决这个问题,可以使用 try catch:

def follow_me(dic, key):
    while True:
        if key not in dic.keys():
            return key
        key = dic[key]


def follow_me2(dic, key):
    try:
        while True:
            key = dic[key]
    except Exception as e:
        return key

import time
d = { i: (i+1) for i in range(10000000) }
start = time.time()
follow_me(d, 0)
print("Using 'in' takes", time.time() - start,"s")

start = time.time()
follow_me2(d, 0)
print("Using 'try' takes", time.time() - start,"s")

给出输出:

Using 'in' takes 2.476428747177124 s
Using 'try' takes 0.9100546836853027 s

【讨论】:

    【解决方案2】:

    认为这就是你要找的,虽然你的问题描述很不清楚:

    def follow_me(d, k):
        while k in d:
            k = d[k]
        return k
    

    请注意,如果字典中的键和值之间存在循环,则此函数中的循环将永远运行。您的示例在'lion''zebra' 之间有一个,并且不完全清楚您打算如何打破这样的循环。如果您只想将每个键展开一次,您可以通过跟踪迄今为止在 set 中看到的值来处理它:

    def follow_me(d, k):
        seen = set()
        while k in d and k not in seen:
            seen.add(k)
            k = d[k]
        return k
    

    这将返回您首先到达的循环中的任何一个键(因此您的示例字典中的follow_me(d, 'zebra') 将在转到zebra => lion => zebra 之后返回'zebra')。如果您想要其他结果,则需要不同的逻辑,并且可能很难做到。

    如果您请求的密钥不在字典中(例如您的示例中的 'aardvark'),则请求的密钥将立即返回。您可以为查找的第一个键添加特殊处理,但这又会使事情变得更加复杂。

    【讨论】:

    • 非常感谢!这正是它应该如何回答!我已经坚持了很长时间了,非常感谢!
    【解决方案3】:

    考虑到存在无限循环,这必须加以处理。您的描述不清楚在这种情况下会发生什么。

    def follow_me(d, key):
        visited_keys = []
        while key not in visited_keys and d[key]:
            visited_keys.append(key)
            key = d[key]
        if not d[key]:
            return key
        return "this hunt has no end"
    

    【讨论】:

    • 几个cmets:您几乎不需要使用dic.keys,您可以直接使用字典来获得相同的效果(成员测试和迭代都是如此)。您在这里也不需要递归。尾递归总是可以被程序员转换成循环,而循环在 Python 中效率更高(它不进行尾调用优化)。
    猜你喜欢
    • 2020-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多