Я хочу объединить связанный ключ, например:
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 on Rails, которая не поддерживалась в течение многих лет и имеет неисправленные ошибки и уязвимости в системе безопасности? Почему вы используете две версии Ruby on Rails в одном проекте? Какое это имеет отношение к Ruby on Rails?
Похоже, вы хотите разделить имя ключа на _
, а затем сгруппировать результаты.
Я бы сделал это так:
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" } }
Я согласен с вашим аргументом об изменении структуры данных, но нельзя ли использовать тот же аргумент, чтобы просто вернуть { a: "value a", b: "value b", c: "value c" }
?
На самом деле я думал, что могут быть и другие префиксы, кроме key
, и поэтому подумал, что вложение key
имеет смысл.
Вход
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"}]}
Если часть key
всегда одна и та же, вы можете сделать:
{ key: my_hash.collect { |k, v| { k.to_s.sub('key_', '').to_sym => v } } }
Здесь есть некоторая путаница, а именно, строки должны быть извлечены из ключей, которые являются символами, изменены, а затем преобразованы обратно в символы. Для этого удобно определить вспомогательные методы, отчасти для того, чтобы их можно было тестировать отдельно.
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
— это привязка к концу строки).
Используйте функцию сопоставления, которая будет проверять или сопоставлять слово key_ или функции, такие как включение или использование регулярных выражений.