【发布时间】:2021-12-01 12:27:21
【问题描述】:
使用tree = lambda: dedfaultdict(tree),我可以替换以下代码:
from collections import defaultdict
END = '$'
words = ['hi', 'hello', 'hiya', 'hey']
root = {}
for word in words:
node = root
for ch in word:
node = node.setdefault(ch, {}) # <---- Code that can be replaced
node[END] = None
与:
from collections import defaultdict
END = '$'
words = ['hi', 'hello', 'hiya', 'hey']
tree = lambda: defaultdict(tree)
root = tree()
for word in words:
node = root
for ch in word:
node = node[ch] # <------ Replaced code
node[END] = None
我真正想要的是每个字典节点都有一个对其父字典节点的反向引用。我可以这样做:
from collections import defaultdict
BACKREF, END = 'BACKREF', '$'
words = ['hi', 'hello', 'hiya', 'hey']
root = {}
for word in words:
node = root
for ch in word:
node = node.setdefault(ch, {BACKREF: node}) # <---- Code I want to replace
node[END] = None
(证明这是有效的:link)
所以,鉴于我能够使用tree = lambda: defaultdict(tree) 替换
node = node.setdefault(ch, {})- 与
node = node[ch]
有没有办法可以使用tree = lambda: default(tree) 的修改版本来替换
node = node.setdefault(ch, {BACKREF: node})- 用更简单的东西,比如
node = node[ch]?
我尝试过类似的方法:
def tree():
_ = defaultdict(tree)
_[BACKREF] = ?
return _
root = tree()
h = root['h']
但这需要tree 知道哪个字典调用了对tree 的调用。例如。在h = root['h'] 中,root['h'] 调用对tree 的调用,因为h 尚未在root 中。 tree 必须知道它是通过调用 root['h'] 调用的,以便它可以执行 h[BACKREF] = root。有没有解决的办法?即使可以做到,这也是个坏主意吗?
我知道反向引用在技术上意味着 trie 将具有循环(而不是真正的树),但我计划遍历 trie 的方式,这不会是一个问题。我想要反向引用的原因是,如果我想从 trie 中删除一个单词,它会很有用。例如,假设我有以下尝试:
我在 root['h']['e']['l']['l']['o'] 并想从 trie 中删除 'hello'。我可以通过将特里树从root['h']['e']['l']['l']['o'] 回溯到root['h']['e']['l']['l'] 到root['h']['e']['l'] 到root['h']['e'] 来做到这一点(我停在这里是因为len(set(root['h']['e'].keys()) - {BACKREF}) > 1。然后我可以简单地做del root['h']['e']['l'] 并且我将切掉@ 987654356@ from 'he' 表示 trie 仍将具有 'hey'。虽然有其他选择,但使用反向引用回溯 trie 将非常容易。
tree = lambda: defaultdict(tree) 上的上下文
使用:
from collections import defaultdict
tree = lambda: defaultdict(tree)
root = tree()
可以创建任意嵌套的dicts。例如。之后:
root['h']['i']
root['h']['e']['l']['l']['o']
root['h']['i']['y']['a']
root['h']['e']['y']
root 看起来像:
{'h': {'i': {'y': {'a': {}}}, 'e': {'y': {}, 'l': {'l': {'o': {}}}}}}
这表示一棵如下所示的树: 使用https://www.cs.usfca.edu/~galles/visualization/Trie.html可视化
【问题讨论】:
-
把相同的
{BACKREF: node}给defaultdict? -
@don'ttalkjustcode 我不确定如何将
{BACKREF: node}放入tree = lambda: defaultdict(tree)或类似的东西。另一个问题是node在定义tree时未定义 - 我该如何解决? -
如果我这样做
root = defaultdict(lambda: {BACKREF: root}),它适用于一个嵌套级别,但不适用于进一步 - 例如root['h']将根据需要导致root = {'h': {'backref': root}},但如果我尝试使用root['h']['i']更进一步,则会导致KeyErrror: 'i',因为root['h']只是一个普通的dict,它本身并不是defaultdict(lambda: {BACKREF: root['h']})。
标签: python trie defaultdict recursive-datastructures