Crystal:检测字典插入是否覆盖键,但不进行两次散列
Crystal: detect if a dictionary insert overwrites a key, but without hashing twice
Crystal 中将键插入 Hash 的规范方法是什么,但如果映射之前确实存在,则会抛出错误。原则上,代码如下:
map = Hash(String, Int32).new
if map.has_key?("foo")
raise "Mapping already exists"
else
map["foo"] = 42
end
我想知道是否可以不用哈希两次?我想出了这个主意,但恕我直言,很难阅读:
map = Hash(String, Int32).new
if map.put("foo", 42) {}
raise "Mapping already exists"
end
(如果映射存在,Map#put
returns 旧值。否则,调用块的结果,即 nil
并计算为 false
.)
有推荐的模式吗?
在性能方面,您已经找到了最佳解决方案。我可能会使用内联块调用这一事实来稍微重写它:
def update(hash, key, value)
hash.put(key, value) { return }
raise "Duplicate entry"
end
但是这里有一个重要的陷阱:在错误情况下哈希仍然会更新:
hash = {"foo" => "bar"}
update(hash, "baz", "quux")
pp hash # => {"foo" => "bar", "baz" => "quux"}
update(hash, "foo", "hello") rescue puts "Failed updating foo" # => Failed updating foo
pp hash # => {"foo" => "hello", "baz" => "quux"}
在不侵入内部 API 的情况下,我认为没有办法避免这种情况。实际上,哈希查找并不是很昂贵,毕竟它是一种针对通过键查找值而优化的数据结构。特别是因为您似乎可以在 API 中加注,这相对来说是一个更昂贵的操作。所以就我个人而言,我会选择你的第一个例子。
Crystal 中将键插入 Hash 的规范方法是什么,但如果映射之前确实存在,则会抛出错误。原则上,代码如下:
map = Hash(String, Int32).new
if map.has_key?("foo")
raise "Mapping already exists"
else
map["foo"] = 42
end
我想知道是否可以不用哈希两次?我想出了这个主意,但恕我直言,很难阅读:
map = Hash(String, Int32).new
if map.put("foo", 42) {}
raise "Mapping already exists"
end
(如果映射存在,Map#put
returns 旧值。否则,调用块的结果,即 nil
并计算为 false
.)
有推荐的模式吗?
在性能方面,您已经找到了最佳解决方案。我可能会使用内联块调用这一事实来稍微重写它:
def update(hash, key, value)
hash.put(key, value) { return }
raise "Duplicate entry"
end
但是这里有一个重要的陷阱:在错误情况下哈希仍然会更新:
hash = {"foo" => "bar"}
update(hash, "baz", "quux")
pp hash # => {"foo" => "bar", "baz" => "quux"}
update(hash, "foo", "hello") rescue puts "Failed updating foo" # => Failed updating foo
pp hash # => {"foo" => "hello", "baz" => "quux"}
在不侵入内部 API 的情况下,我认为没有办法避免这种情况。实际上,哈希查找并不是很昂贵,毕竟它是一种针对通过键查找值而优化的数据结构。特别是因为您似乎可以在 API 中加注,这相对来说是一个更昂贵的操作。所以就我个人而言,我会选择你的第一个例子。