Python 非递归函数follow_me(d,s),其中d是字典,s是字符串
我目前正在准备考试,一直在努力解决这个问题,我最大的问题似乎是正确地反复阅读字典。问题本身是一个非递归函数follow_me(d,s),其中d是字典,s是字符串。该字符串可能是字典的键。与该键相关联的值可以是字典的另一个键。继续查找键,直到找到一个没有关联值的键。然后,把钥匙还给我 我试着只处理键,然后是值,但是,似乎迭代最理想的方法是在d.items()中使用k,v。我对python非常陌生,这可能并不理想,因为我可能缺乏一些理解,这可能是我无法找到解决方案的最大问题Python 非递归函数follow_me(d,s),其中d是字典,s是字符串,python,python-3.x,function,dictionary,Python,Python 3.x,Function,Dictionary,我目前正在准备考试,一直在努力解决这个问题,我最大的问题似乎是正确地反复阅读字典。问题本身是一个非递归函数follow_me(d,s),其中d是字典,s是字符串。该字符串可能是字典的键。与该键相关联的值可以是字典的另一个键。继续查找键,直到找到一个没有关联值的键。然后,把钥匙还给我 我试着只处理键,然后是值,但是,似乎迭代最理想的方法是在d.items()中使用k,v。我对python非常陌生,这可能并不理想,因为我可能缺乏一些理解,这可能是我无法找到解决方案的最大问题 def follow_m
def follow_me(d, s):
for k,v in d.items():
try:
if s == k:
s = v
continue
else:
return s
except:
break
预期成果:
跳蚤
跳蚤
蜘蛛
假的
土豚
实际结果:
跳蚤
狐狸
麻雀
斑马
土豚
斑马被认为是虚假的,因为它在斑马和狮子之间无限循环。任何帮助/提示都将不胜感激。您很接近,但您不需要重复按键;一个简单的
while
循环就可以了
def follow_me(d, s):
while s in d:
s = d[s]
return s
也就是说,您应该通过将选中的值添加到集合中来检查循环:
def follow_me(d, s):
checked_keys = set()
while s in d:
checked_keys.add(s)
s = d[s]
if s in checked_keys:
raise Exception('Cycle detected')
return s
这个问题需要一些背景词汇和理论来构建解决方案
输入字典表示一个名为的结构。具体地说,它是一个图形,因为它不是双向的(也就是说,“獾”和“doe”之间的边意味着我们可以从“獾”到“doe”,但不一定相反)。图形已断开连接,因为无法从图形中的某些节点连接到其他节点
让我们直观地对图形进行建模:
[badger]-->[doe]-->[fox]-->[hen]-->[flea]
[sparrow]-->[spider] [zebra]------+
^ |
| v
+-------[lion]
我们可以看到“斑马”和“狮子”之间有一个连接,并且有三个子图是断开的。跟踪边就像索引到字典的键以访问其邻居一样简单(此图中的节点从来没有多个邻居,这是一个很好的简化)
现在我们已经有了概念框架,下一步是确定如何从给定的原始节点遍历图形,直到找到一个循环或命中一个没有出站边的节点。有很多种方法可以做到这一点,但其中一种方法是在图形上运行
在代码中运行DFS可以归结为使用数据结构,可以是显式堆栈形式,也可以是。递归DFS的伪代码很简单:
def DFS(graph, root, target):
if root == target: return True
for neighbor in graph[root]:
if DFS(graph, neighbor, target):
return True
return False
这在树上很好,树是没有圈的有向图,但在提供的输入上会失败,因为它包含圈。我们还可以简化DFS,因为我们保证只有一个邻居,而不关心目标目的地。但是,有必要跟踪终端节点,而不是简单的布尔值。综合起来,我们得到以下伪代码:
def DFS(graph: dict, root: str, visited: set):
if root in visited:
return False
elif root not in graph:
return root
visited.add(root)
return DFS(graph, graph[root], visited)
这也可以像您的尝试一样迭代编写,如:
def follow_me(graph, target):
visited = set()
while target in graph:
if target in visited: return False
visited.add(target)
target = graph[target]
return target
输出
flea
flea
spider
False
aardvark
逻辑非常直截了当,代码也不言自明。你根本不应该在字典上迭代。你的v不应该是你的值吗?为什么要取v+1?嗯,那么,在没有找到关联的键之前,怎么可能从一个键到另一个值,或者从另一个键到另一个值?很抱歉提出疑问,我只是看不到另一种方法。@Axios,是的,v是字典的值,v+1应该是在下面的例子中,follow_me(d,“zebra”)不能在“zebra”和“lion”之间无限循环。如果检测到一个循环,follow_me应该返回布尔值False,但是,我这样使用它很可能是错误的,正如我所说的,我非常缺乏经验,它可能不适用于字典。这里的相同问题:。顺便问一下,你们认识吗?:)我不太认为事情会这么简单,也许我对它研究得太多是我最大的问题。而不是引发异常,我必须返回false,好像我真的引发了它,它打破了循环。不过,非常感谢您,我将用pythontutor来介绍它并从中学习。这种方法是干净的,但会在的循环中卡住,而跟踪我(d,'zebra')
。OP想要为重复模式返回False
。@HenryYik只需替换第二个代码片段中的raise:)右-忽略了那一个。哈哈,是的,我从一开始就注意到实际上是为了摆脱raise异常,因为它与预期的输出冲突,并用return False替换它,我欣赏你的教育思想:)这是一个教育作业的问题。这个答案没有解释,只是把代码交出来。这有什么帮助?@ggorlen我认为这不值得投反对票。。。人们确实从正确的解决方案中学习。不过,这是我的拙见。谢谢@complexedphenomenom,我很感激你的回答,对我来说,直接解决这个问题可能不是最好的办法,而是我为了学习的目的改编了一些作品,不过,无论如何,谢谢你,这真的很有帮助!除了缺乏解释之外,还有其他问题:1)O(n)搜索每个节点元素上的列表。为什么不使用集合进行O(1)查找?2) 单字母变量贯穿始终。3) 糟糕的样式(条件周围不必要的括号,在v=d[s]
之间没有空格,v
是一个冗余变量,只需返回s
?)。4) 不必要的条件。弗莱克斯的解决方案更干净、更有效。@ggorlen非常感谢你的建议。该死,我不敢相信你在帮助我方面付出了那么多努力,我非常感谢。至于它,我相信我必须以一种更简单的方式来处理这个循环,正如其他两个答案所说的那样。我觉得好像我可以从你的话中学到很多东西,这些东西可以帮助我在前进的道路上变得更先进,所以非常感谢你,这个问题中的一个有力的例子是事实上避免被斑马和狮子之间的循环所困
def follow_me(d, s):
if s not in d:
return s
else:
k = [] # save the chain keys
while (s in d):
if s in k:
return False
k.append(s)
s = d[s]
return s
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'))
flea
flea
spider
False
aardvark