ruby 组合哈希相关键

问题描述 投票:0回答:4

我想组合相关的键例如:

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

ruby ruby-on-rails-3 ruby-on-rails-4
4个回答
4
投票

我会这样做:

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" } }

2
投票

如果

key
部分总是一样的,你可以这样做:

{ key: my_hash.collect { |k, v| { k.to_s.sub('key_', '').to_sym => v } } }

1
投票

输入

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"}]}

0
投票

这里有些混乱,即必须从作为符号的键中提取字符串,进行修改,然后再转换回符号。定义辅助方法来做到这一点很方便,部分原因是它们可以单独测试。

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
是字符串结束锚点)。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.