我想组合相关的键例如:
my_hash = {key_a: "value a", key_b: "value b", key_c: "value c"}
我想要的结果是:
{ key:
[
{ a: "value a" },
{ b: "value b" },
{ c: "value c" }
]
}
通过明确获取每个键可以很容易地做到这一点,但问题是,它可以定义动态键。
问题是
key_
可以是任何一个,你无法确定key_
之后是什么。可以是key_r
、key_w
、key_z
我会这样做:
my_hash = { key_a: "value a", key_b: "value b", key_c: "value c" }
my_hash.each_with_object({}) do |(key, value), result|
prefix, suffix = key.to_s.split('_').map(&:to_sym)
result[prefix] ||= [];
result[prefix] << { suffix => value }
end
#=> { key: [{ a: "value a" }, { b: "value b" }, { c: "value c" }] }
我建议稍微改变一下数据结构,因为在 IMO 看来,嵌套哈希值只包含键/值对是没有意义的:
my_hash.each_with_object({}) do |(key, value), result|
prefix, suffix = key.to_s.split('_').map(&:to_sym)
result[prefix] ||= {};
result[prefix][suffix] = value
end
#=> { key: { a: "value a", b: "value b", c: "value c" } }
如果
key
部分总是一样的,你可以这样做:
{ key: my_hash.collect { |k, v| { k.to_s.sub('key_', '').to_sym => v } } }
输入
my_hash = {key_a: "value a", key_b: "value b", key_c: "value c"}
代码
new_hash = { key: [] }
my_hash.each_key do |key|
if key.to_s.start_with?("key_")
new_key = key.to_s.split("_")[1].to_sym
new_hash[:key] << { new_key => my_hash[key] }
end
end
p new_hash
输出:
{:key=>[{:a=>"value a"}, {:b=>"value b"}, {:c=>"value c"}]}
这里有些混乱,即必须从作为符号的键中提取字符串,进行修改,然后再转换回符号。定义辅助方法来做到这一点很方便,部分原因是它们可以单独测试。
def key_prefix(key_sym)
key_sym[/[^_]*/].to_sym
end
def key_suffix(key_sym)
key_sym[/[^_]*\z/].to_sym
end
例如,
key_prefix(:key_ccc) #=> :key
key_suffix(:key_ccc) #=> :ccc
见符号#[].
然后我们可以写
my_hash = {key_a: "value a", key_b: "value b", key_ccc: "value c"}
{key_prefix(my_hash.first.first)=>my_hash.map {|k,v| { key_suffix(k)=>v}}}
#=> {:key=>[{:a=>"value a"}, {:b=>"value b"}, {:ccc=>"value c"}]}
正则表达式
/[^_]*/
匹配字符类*
中的零个或多个([^_]
)字符(尽可能多),后者由除(^
)下划线以外的所有字符组成。正则表达式 /[^_]*\z/
是相同的,除了匹配必须在字符串的末尾(\z
是字符串结束锚点)。