Base.ht_keyindex2! 函数的用法


#1

遇到了好几次 Base.ht_keyindex2! 函数的调用,但是不清楚这个函数的用法,在 help 和 Google 中也没找到详细的解释说明

help?> Base.ht_keyindex2!
  No documentation found.

  Base.ht_keyindex2! is a Function.

  # 1 method for generic function "ht_keyindex2!":
  [1] ht_keyindex2!(h::Dict{K,V}, key) where {K, V} in Base at dict.jl:305

有人遇到过这个函数调用吗,可以解释一下这函数吗?


#2

github 上搜了一下,找到了注释

# get the index where a key is stored, or -pos if not present
# and the key would be inserted at pos
# This version is for use by setindex! and get!
function ht_keyindex2!(h::Dict{K,V}, key) where V where K
—— julia/dict.jl at master · JuliaLang/julia

对比了下 ht_keyindex2!ht_keyindex 的源码。在 key 不存在时,ht_keyindex 返回 -1,而 ht_keyindex2! 使用 hashindex 取得 key 应当在的 index 位置,返回其相反数。

顺带测试了一下,这个函数并不会修改原哈希表(至少在 key 不存在时是这样),它带 ! 后缀的原因是,用这个函数时,可能引起 rehash 操作。依赖它实现的 setindex!get! 则会修改原哈希表。

总之这个函数让 key 不存在时自动新增 key 变得方便了。


#3

好吧 :joy:,还是很感谢


#4

在 github 上搜的时候发现都是第三方库用得较多,一般是在实现特殊的哈希表,顺带实现相应的操作时(也就是写 julia 库),才会用到。

平常用 ht_keyindex 应该就够用了。 不用 getindex 大概是因为查询不存在的键时会报错。 口胡这两个函数目的不同


#5

我就是读 JuAFEM (也是第三方的库) 时看到的,好几个地方用到的。可以解释一下 ht_keyindex 的用法吗? help 也没结果。


#6

julia 哈希表的键值对分别存在两个 Array 里,所以会有相应的引索,ht_keyindex 就是用来取对应键的引索值,找不到就返回 -1

ht_keyindex2! 也差不多,只是在取不存在的键时,会返回那个键应在位置引索值的相反数 (真绕口,不如看源码)

julia> h = Dict("A"=>1, "B"=>2)
Dict{String,Int64} with 2 entries:
  "B" => 2
  "A" => 1

julia> h.keys # 存放键的数组
16-element Array{String,1}:
 #undef
    "B"
    "A"
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef

julia> h.vals # 存放值的数组
16-element Array{Int64,1}:
 244450080
         2
         1
 244449856
 244449856
 244449856
 244449856
 244452208
 244452208
 244449856
 244449856
 244449856
 244514840
 244514840
 244449856
 257113136

julia> Base.ht_keyindex(h, "B") # 取 “B” 这个键在数组中的位置
2

julia> h.keys[2] # 验证一下
"B"

julia> Base.ht_keyindex(h, "C") # 不存在的键返回 -1
-1

ht_keyindex2!

接以上代码

  1. 看上去直接给 h.valsh.keys 赋值并不能新增键值对。
  2. 键不存在时, ht_keyindex2! 返回的值会告诉你,插入对应的键会放在哪。(其实这里颠倒了因果,因为插入的位置就是根据 ht_keyindex2! 的返回值确定的,ref:julia/dict.jl at master · JuliaLang/julia)
julia> h.keys[4] = "C"
"C"

julia> h
Dict{String,Int64} with 2 entries:
  "B" => 2
  "A" => 1

julia> h.vals[4] = 3
3

julia> h
Dict{String,Int64} with 2 entries:
  "B" => 2
  "A" => 1

julia> h.vals
16-element Array{Int64,1}:
 244450080
         2
         1
         3
 244449856
 244449856
 244449856
 244452208
 244452208
 244449856
 244449856
 244449856
 244514840
 244514840
 244449856
 257113136

julia> h.keys
16-element Array{String,1}:
 #undef
    "B"
    "A"
    "C"
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef

julia> Base.ht_keyindex2!(h, "C") # 如果有键 “C”,应该放在第 6 位
-6

julia> setindex!(h, 3, "C") # 插入键值对
Dict{String,Int64} with 3 entries:
  "B" => 2
  "A" => 1
  "C" => 3

julia> h.keys # 检查效果
16-element Array{String,1}:
 #undef
    "B"
    "A"
    "C"
 #undef
    "C"
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef

#7

好的,非常感谢!


#8

BTW,Base里面没有export的函数可能会break,用的时候需要注意