我有未分类的键值对映射。
input = {
"xa" => "xavalue",
"ab" => "abvalue",
"aa" => "aavalue",
"ba" => "bavalue",
}
现在我想按键对它们进行排序,然后按键的第一个字符将它们分成几个部分。与此类似:
output1 = {
"a" => {
"aa" => "aavalue",
"ab" => "abvalue",
},
"b" => {
"ba" => "bavalue",
},
"x" => {
"xa" => "xavalue",
},
}
虽然这是相对微不足道的,但我正在寻找一种简洁的方法来表达ruby中从输入到输出1的转换。 (我的方法可能比红宝石标准过于冗长)
您可能还注意到地图(通常)没有订购。因此,除非我手动对键进行排序并包含对地图的访问权限,否则上述数据结构将无法正常工作。那么如何在ruby中创建一个有序的有序映射?或者已经有一个?
如果有序地图方法不那么容易,我将不得不将最终结构更改为如下所示。我再次寻找一些简洁的ruby代码,从输入到输出2。
output2 = [
{
"name" => "a",
"keys" => [ "aa", "ab" ],
"values" => [ "aavalue", "abvalue" ],
},
{
"name" => "b",
"keys" => [ "ba" ],
"values" => [ "bavalue" ],
},
{
"name" => "x",
"keys" => [ "xa" ],
"values" => [ "xavalue" ],
}
]
答案 0 :(得分:2)
据我所知,Ruby中没有排序哈希/映射的概念,所以你只能使用这个好的旧数组。您可能希望从此代码开始:
output = input.inject({}) { |acc, pair|
letter = pair.first[0].chr
acc[letter] ||= {}
acc[letter][pair.first] = pair.last
acc
}.sort
这将为您提供
形式的数据结构[ ["a", {"aa"=>"aavalue",
"ab"=>"abvalue"}],
["b", {"ba"=>"bavalue"}],
["x", {"xa"=>"xavalue"}]]
通过将组件数组映射到哈希...
output.map {|pair| {pair.first => pair.last}}
您可以将其转换为类似
的内容[{"a"=>{"aa"=>"aavalue",
"ab"=>"abvalue"}},
{"b"=>{"ba"=>"bavalue"}},
{"x"=>{"xa"=>"xavalue"}}]
使用类似的地图,您可以到达列出的最后一个表单(output2):
output2 = output.map { |pair|
hash = pair.last
{ 'name' => pair.first,
'keys' => hash.keys,
'values' => hash.values }
}
答案 1 :(得分:1)
我是一个pythonista,但我还是试过了:
class Hash
def clustered
clustered = Hash.new
sort.each do | key, value |
first = key[0,1]
unless clustered.has_key?(first)
clustered[first] = Hash.new
end
clustered[first][key] = value
end
clustered
end
end
答案 2 :(得分:1)
output = input.inject({}){ |h, p| k,v=p; (h[k[0..0]] ||= {})[k] = v; h}
答案 3 :(得分:1)
不幸的是,没有一个答案是完整的。所以我基于Thiago的解决方案想出了这个:
output1 = input.inject({}) { |acc, pair|
letter = pair.first[0].chr
acc[letter] ||= {}
acc[letter][pair.first] = pair.last
acc
}.sort
output2 = output1.inject([]) { |acc, pair|
acc << {
'name' => pair.first,
'keys' => pair.last.keys(),
'values' => pair.last.values()
}
acc
}