Итак, вот в чем дело, я много лет гуглял, чтобы найти решение этой проблемы, и хотя их там много, похоже, они не выполняют ту работу, которую я ищу.
В основном у меня есть массив, структурированный так
["item 1", "item 2", "item 3", "item 4"]
Я хочу преобразовать это в хэш, чтобы он выглядел так
{ "item 1" => "item 2", "item 3" => "item 4" }
то есть элементы в «четных» индексах являются ключами, а элементы в «нечетных» индексах являются значениями.
Есть идеи, как сделать это чисто? Я полагаю, что методом грубой силы было бы просто вытащить все четные индексы в отдельный массив, а затем зациклить их, чтобы добавить значения.
*
называется знак оператора. Он берет массив и преобразует его в буквальный список элементов. Итак*[1,2,3,4]
=>1, 2, 3, 4
. В этом примере вышесказанное эквивалентно выполнениюHash["item 1", "item 2", "item 3", "item 4"]
. ИHash
имеет[]
метод, который принимает список аргументов (создает четные ключи ключей и нечетные значения индексов), ноHash[]
не принимает массив, поэтому мы разбиваем массив на части с помощью*
.Hash[a.each_slice(2).to_a]
.В Ruby 2.1.0 появился
to_h
метод Array, который делает то, что вам нужно, если ваш исходный массив состоит из массивов пар ключ-значение: http://www.ruby-doc.org/core-2.1.0/Array.html#method -i-to_h .источник
bar
должен быть символ, а символ:2
должен быть целым числом. Итак, ваше выражение исправленоa = [[:foo, 1], [:bar, 2]]
).Просто используйте
Hash.[]
со значениями в массиве. Например:источник
*arr
преобразуетсяarr
в список аргументов, поэтому это вызывает[]
метод Hash с содержимым arr в качестве аргументов.Или, если у вас есть массив
[key, value]
массивов, вы можете сделать:источник
Hash[*arr]
{ [1, 2] => [3, 4] }
. И поскольку в заголовке вопроса написано «Array to Hash», а встроенный метод «Hash to Array» делает так:{ 1 => 2, 3 => 4}.to_a # => [[1, 2], [3, 4]]
я думал, что более чем один может закончить здесь, пытаясь получить обратное значение встроенного метода «Hash to Array». Собственно, так все и закончилось.Hash[arr]
сделает работу за вас.#inject
метода. С#merge!
,#each_with_object
должен был быть использован. Если#inject
настаивают на,#merge
а не#merge!
должны были быть использованы.Вот что я искал, когда гуглял это:
[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}
источник
merge
, он создает и отбрасывает новый хэш за цикл итерации и очень медленно. Если у вас есть массив хэшей, попробуйте[{a:1},{b:2}].reduce({}, :merge!)
вместо этого - он объединит все в один (новый) хеш..reduce(&:merge!)
[{a: 1}, {b: 2}].reduce(&:merge!)
оценивает{:a=>1, :b=>2}
[{a: 1}, {b: 2}].reduce(&:merge!)
это то же самое,[{a: 1}, {b: 2}].reduce { |m, x| m.merge(x) }
что и то же самое, что и[{b: 2}].reduce({a: 1}) { |m, x| m.merge(x) }
.Enumerator
включает в себяEnumerable
. Так как2.1
,Enumerable
также есть метод#to_h
. Вот почему мы можем написать:Потому что
#each_slice
без блока дает намEnumerator
, и согласно приведенному выше объяснению, мы можем вызвать#to_h
методEnumerator
объекта.источник
Вы можете попробовать так, для одного массива
для массива массива
источник
или, если вы ненавидите
Hash[ ... ]
:или, если вы ленивый поклонник неработающего функционального программирования:
источник
Hash[ ... ]
но хотите использовать его как цепочечный метод (как вы можете сделать с этимto_h
), вы можете объединить предложения Бориса и написать:arr.each_slice( 2 ).map { |e| e }.tap { |a| break Hash[a] }
Все ответы предполагают, что начальный массив уникален. OP не указывал, как обрабатывать массивы с дублирующимися записями, что приводит к дублированию ключей.
Давайте посмотрим на:
Вы потеряете
item 1 => item 2
пару, поскольку она переопределена bijitem 1 => item 5
:Все методы, включая
reduce(&:merge!)
результат в том же удалении.Вполне возможно, что это именно то, что вы ожидаете. Но в других случаях вы, вероятно, захотите получить результат со
Array
значением for:Наивным способом было бы создать вспомогательную переменную, хэш, который имеет значение по умолчанию, и затем заполнить его в цикле:
Можно было бы использовать
assoc
иreduce
делать выше в одной строке, но это становится гораздо сложнее рассуждать и читать.источник