ruby合并hash相关键

kninwzqo  于 2023-05-17  发布在  Ruby
关注(0)|答案(4)|浏览(128)

我想合并相关的键,例如:

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_rkey_wkey_z

ykejflvf

ykejflvf1#

我会这样做:

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

我建议稍微改变一下数据结构,因为在我看来,嵌套的哈希只有一个键/值对是没有意义的:

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

plupiseo2#

如果key部分始终相同,则可以执行以下操作:

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

axkjgtzd3#

输入

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

fkaflof64#

这里有一些混乱,即字符串必须从符号键中提取,修改,然后转换回符号。为了方便起见,可以定义帮助器方法来实现这一点,部分原因是可以单独测试它们。

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

相关问题