我有这样的哈希表:
h={"c4"=>1, "c8"=>2, "ec"=>3, "a"=>4, "e4"=>5, "1"=>6, "8"=>7}
我可以将值2视为:h["c8"]
我想将哈希表转换为嵌入式哈希表,如下所示:
h={"c"=>{"4"=>1, "8"=>2}, "e"=>{"c"=>3, "4"=>5}, "a"=>4, "1"=>6, "8"=>7}
所以我可以分别以类似的方式访问值2:h["c"]["8"]
和所有其他值。
总而言之而不是:
h["c8"]
我更愿意使用:
h["c"]["8"]
因为我想在javascript中识别字符串。所以我想用Ruby构建一个非常大的嵌入式哈希表,将其转储到JSON并加载到javascript中。这种嵌入式哈希表比原始哈希表更容易查找。密钥来自MD5,散列了一些原始值,即文件名,然后从MD5散列键的开头找到最小的片段,这些片段仍然是unq。
另一个较长的例子:
h={"c4"=>1,
"c8"=>2,
"ec"=>3,
"a8"=>4,
"e4"=>5,
"1"=>6,
"8"=>7,
"c9"=>8,
"4"=>9,
"d"=>10,
"6"=>11,
"c2"=>12,
"c5"=>13,
"aa"=>14}
将是:
h={"c"=>{"4"=>1, "8"=>2, "9"=>8, "2"=>12, "5"=>13},
"e"=>{"c"=>3, "4"=>5},
"a"=>{"8"=>4, "a"=>14},
"1"=>6,
"8"=>7,
"4"=>9,
"d"=>10,
"6"=>11}
更长的例子:
h={"c4"=>1, "c8"=>2, "ec"=>3, "a8"=>4, "e4"=>5, "16"=>6, "8f"=>7, "c9"=>8, "45"=>9, "d3"=>10, "65"=>11, "c2"=>12, "c5"=>13, "aa"=>14, "9b"=>15, "c7"=>16, "7"=>17, "6f"=>18, "1f0"=>19, "98"=>20, "3c"=>21, "b"=>22, "37"=>23, "1ff"=>24, "8e"=>25, "4e"=>26, "0"=>27, "33"=>28, "6e"=>29, "3417"=>30, "c1"=>31, "63"=>32, "18"=>33, "e3"=>34, "1c"=>35, "19"=>36, "a5b"=>37, "a57"=>38, "d67"=>39, "d64"=>40, "3416"=>41, "a1"=>42}
将是:
h={"c"=>{"4"=>1, "8"=>2, "9"=>8, "2"=>12, "5"=>13, "7"=>16, "1"=>31},
"e"=>{"c"=>3, "4"=>5, "3"=>34},
"a"=>{"8"=>4, "a"=>14, "5"=>{"b"=>37, "7"=>38}, "1"=>42},
"1"=>{"6"=>6, "f"=>{"0"=>19, "f"=>24}, "8"=>33, "c"=>35, "9"=>36},
"8"=>{"f"=>7, "e"=>25},
"4"=>{"5"=>9, "e"=>26},
"d"=>{"3"=>10, "6"=>{"7"=>39, "4"=>40}},
"6"=>{"5"=>11, "f"=>18, "e"=>29, "3"=>32},
"9"=>{"b"=>15, "8"=>20},
"7"=>17,
"3"=>{"c"=>21, "7"=>23, "3"=>28, "4"=>{"1"=>{"7"=>30, "6"=>41}}},
"b"=>22,
"0"=>27}
我尝试解决这个问题有点难看并使用“eval”,“h”是原始哈希:
nested_hash={}
h.keys.each{|k|
k.split(//).each_with_index{|b,i|
if nested_hash.dig(*k[0..i].split(//))==nil then
eval("nested_hash"+k[0..i].split(//).map{|z| "[\"#{z}\"]"}.join+"={}")
end
if i==k.size-1 then
eval("nested_hash"+k[0..i].split(//).map{|z| "[\"#{z}\"]"}.join+"=h[k]")
end
};
};
答案 0 :(得分:3)
您正在描述Trie。 我对triez和trie宝石有很好的体验。
您需要在哈希中迭代key,value
对,并使用叶子上的值将md5字符串添加到trie中。
最后,您将整个结构导出到嵌套哈希或在特里节点上定义to_json
。
PS:你的问题很有意思,也很有问题。你没有提供任何代码,所以我也不会;)
答案 1 :(得分:1)
可以使用reduce
和chars
的组合来完成。
h={"c4"=>1, "c8"=>2, "ec"=>3, "a"=>4, "e4"=>5, "1"=>6, "8"=>7}
result = h.reduce({}) do |memo, (k,v)|
key, nested_key = k.to_s.chars
if nested_key
memo[key] ||= {}
memo[key][nested_key] = v
else
memo[key] = v
end
memo
end
# => {"c"=>{"4"=>1, "8"=>2}, "e"=>{"c"=>3, "4"=>5}, "a"=>4, "1"=>6, "8"=>7}
如果你想拥有超过1个字符或更多嵌套级别的键,你需要多做一些工作,但这有希望给你一个想法。
答案 2 :(得分:1)
根据对OP发布的问题的评论,我假设没有k1
和k2
,k2.size > k1.size
的密钥{{1} }。
<强>代码强>
k2[0, ki.size] == k1
<强>实施例强>
#1
def splat_hash(h)
h.select { |k,_| k.size > 1 }.
group_by { |k,_| k[0] }.
map { |k0,a| [k0, splat_hash(a.map { |k,v| [k[1..-1],v] }.to_h)] }.
to_h.
merge(h.select{ |k,_| k.size == 1 })
end
#2
h = {"c4"=>1, "c8"=>2, "ec"=>3, "a"=>4, "e4"=>5, "1"=>6, "8"=>7}
splat_hash h
#=> {"c"=>{"4"=>1, "8"=>2}, "e"=>{"c"=>3, "4"=>5}, "a"=>4, "1"=>6, "8"=>7}
#3
h = { "c4"=>1, "c8"=>2, "ec"=>3, "a8"=>4, "e4"=>5, "16"=>6, "8f"=>7, "c9"=>8,
"45"=>9, "d3"=>10, "65"=>11, "c2"=>12, "c5"=>13, "aa"=>14, "9b"=>15,
"c7"=>16, "7"=>17, "6f"=>18, "1f0"=>19, "98"=>20, "3c"=>21, "b"=>22,
"37"=>23, "1ff"=>24, "8e"=>25, "4e"=>26, "0"=>27, "33"=>28, "6e"=>29,
"3417"=>30, "c1"=>31, "63"=>32, "18"=>33, "e3"=>34, "1c"=>35, "19"=>36,
"a5b"=>37, "a57"=>38, "d67"=>39, "d64"=>40, "3416"=>41, "a1"=>42 }
splat_hash h
#=> {"c"=>{"4"=>1, "8"=>2, "9"=>8, "2"=>12, "5"=>13, "7"=>16, "1"=>31},
# "e"=>{"c"=>3, "4"=>5, "3"=>34},
# "a"=>{"5"=>{"b"=>37, "7"=>38}, "8"=>4, "a"=>14, "1"=>42},
# "1"=>{"f"=>{"0"=>19, "f"=>24}, "6"=>6, "8"=>33, "c"=>35, "9"=>36},
# "8"=>{"f"=>7, "e"=>25},
# "4"=>{"5"=>9, "e"=>26},
# "d"=>{"6"=>{"7"=>39, "4"=>40}, "3"=>10},
# "6"=>{"5"=>11, "f"=>18, "e"=>29, "3"=>32},
# "9"=>{"b"=>15, "8"=>20},
# "3"=>{"4"=>{"1"=>{"7"=>30, "6"=>41}}, "c"=>21, "7"=>23, "3"=>28},
# "7"=>17,
# "b"=>22,
# "0"=>27}
<强>解释强>
我认为展示正在发生的事情的最佳方式是在代码中添加一些h = { "a"=>1, "ba"=>2, "bb"=>3, "caa"=>4, "cab"=>5, "daba"=>6, "dabb"=>7, "dabcde"=>8 }
splat_hash h
#=> {"b"=>{"a"=>2, "b"=>3},
# "c"=>{"a"=>{"a"=>4, "b"=>5}},
# "d"=>{"a"=>{"b"=>{"c"=>{"d"=>{"e"=>8}},"a"=>6, "b"=>7}}},
# "a"=>1}
语句并使用示例运行它。
puts
INDENT_SIZE = 6
def putsi(str)
puts "#{' ' * @indent}#{str}"
end
def indent
@indent = (@indent ||= 0) + INDENT_SIZE
end
def undent
@indent -= INDENT_SIZE
end
def splat_hash(h)
puts
indent
putsi "enter splat_hash with h=#{h}"
h.select { |k,_| k.size > 1 }.
tap { |g| putsi " select > 1 = #{g}" }.
group_by { |k,_| k[0] }.
tap { |g| putsi " group_by = #{g}" }.
map { |k0,a| putsi " calling splat_hash";
[k0, splat_hash(a.map { |k,v| [k[1..-1],v] }.to_h)] }.
tap { |a| putsi " map = #{a}" }.
to_h.
tap { |g| putsi " to_h = #{g}" }.
merge(h.select{ |k,_| k.size == 1 }).
tap { |g| putsi " returning g = #{g}" }.
tap { undent }
end
h = {"c4"=>1, "c8"=>2, "ec"=>3, "faa"=>4, "e4"=>5, "fab"=>6, "1"=>7 }
splat_hash h
enter splat_hash with h={"c4"=>1, "c8"=>2, "ec"=>3, "faa"=>4, "e4"=>5,
"fab"=>6, "1"=>7}
select > 1 = {"c4"=>1, "c8"=>2, "ec"=>3, "faa"=>4, "e4"=>5, "fab"=>6}
group_by = {"c"=>[["c4", 1], ["c8", 2]], "e"=>[["ec", 3], ["e4", 5]],
"f"=>[["faa", 4], ["fab", 6]]}
calling splat_hash
enter splat_hash with h={"4"=>1, "8"=>2}
select > 1 = {}
group_by = {}
map = []
to_h = {}
returning g = {"4"=>1, "8"=>2}
calling splat_hash
enter splat_hash with h={"c"=>3, "4"=>5}
select > 1 = {}
group_by = {}
map = []
to_h = {}
returning g = {"c"=>3, "4"=>5}
calling splat_hash
enter splat_hash with h={"aa"=>4, "ab"=>6}
select > 1 = {"aa"=>4, "ab"=>6}
group_by = {"a"=>[["aa", 4], ["ab", 6]]}
calling splat_hash
答案 3 :(得分:0)
灵感来自JavaScript的超简单非递归(迭代)解决方案,变量to
就像结构中的指针一样:
def nested_hash(h)
bh={};
h.keys.each{|k|
to=bh
k[0..-2].each_char{|c|
if to[c]==nil then
to[c]={}
end
to=to[c]
}
to[k[-1]]=h[k]
}
return bh
end