Array to Hash Ruby - PullRequest
       14

Array to Hash Ruby

182 голосов
/ 27 октября 2010

Ладно, вот в чем дело, я годами гуглял, чтобы найти решение этой проблемы, и хотя их там много, похоже, они не выполняют ту работу, которую я ищу.

В основном у меня есть массив, структурированный так

["item 1", "item 2", "item 3", "item 4"] 

Я хочу преобразовать его в хэш, чтобы он выглядел следующим образом

{ "item 1" => "item 2", "item 3" => "item 4" }

т.е. элементы, находящиеся на четноминдексы - это ключи, а элементы в «нечетных» индексах - это значения.

Есть идеи, как сделать это чисто?Я полагаю, что методом грубой силы было бы просто вытащить все четные индексы в отдельный массив и затем зациклить их, чтобы добавить значения.

Ответы [ 8 ]

346 голосов
/ 27 октября 2010
a = ["item 1", "item 2", "item 3", "item 4"]
h = Hash[*a] # => { "item 1" => "item 2", "item 3" => "item 4" }

Вот и все.* называется оператором splat .

Одно предостережение на @Mike Lewis (в комментариях): «Будьте очень осторожны с этим. Ruby расширяет знаки в стеке.сделайте это с большим набором данных, ожидайте, что вы разбьете свой стек. "

Итак, для большинства случаев общего использования этот метод хорош, но используйте другой метод, если вы хотите выполнить преобразование для большого количества данных.Например, @ Łukasz Niemier (также в комментариях) предлагает этот метод для больших наборов данных:

h = Hash[a.each_slice(2).to_a]
95 голосов
/ 14 января 2014

В Ruby 2.1.0 появился метод to_h для массива, который делает то, что вам нужно, если ваш исходный массив состоит из массивов пар ключ-значение: http://www.ruby -doc.org / core-2.1.0 / Array.html # метод-я-to_h .

[[:foo, :bar], [1, 2]].to_h
# => {:foo => :bar, 1 => 2}
27 голосов
/ 27 октября 2010

Просто используйте Hash.[] со значениями в массиве. Например:

arr = [1,2,3,4]
Hash[*arr] #=> gives {1 => 2, 3 => 4}
25 голосов
/ 11 декабря 2012

Или, если у вас есть массив [key, value] массивов, вы можете сделать:

[[1, 2], [3, 4]].inject({}) do |r, s|
  r.merge!({s[0] => s[1]})
end # => { 1 => 2, 3 => 4 }
10 голосов
/ 16 сентября 2015

Это то, что я искал, когда гуглял это:

[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}

8 голосов
/ 27 июля 2014

Enumerator включает Enumerable.Поскольку 2.1, Enumerable также имеет метод #to_h.Поэтому мы можем написать: -

a = ["item 1", "item 2", "item 3", "item 4"]
a.each_slice(2).to_h
# => {"item 1"=>"item 2", "item 3"=>"item 4"}

Поскольку #each_slice без блока дает нам Enumerator, и согласно приведенному выше объяснению мы можем вызвать метод #to_hна объекте Enumerator.

6 голосов
/ 06 марта 2015

Вы можете попробовать вот так, для одного массива

irb(main):019:0> a = ["item 1", "item 2", "item 3", "item 4"]
  => ["item 1", "item 2", "item 3", "item 4"]
irb(main):020:0> Hash[*a]
  => {"item 1"=>"item 2", "item 3"=>"item 4"}

для массива массива

irb(main):022:0> a = [[1, 2], [3, 4]]
  => [[1, 2], [3, 4]]
irb(main):023:0> Hash[*a.flatten]
  => {1=>2, 3=>4}
5 голосов
/ 02 июня 2013
a = ["item 1", "item 2", "item 3", "item 4"]
Hash[ a.each_slice( 2 ).map { |e| e } ]

или, если вы ненавидите Hash[ ... ]:

a.each_slice( 2 ).each_with_object Hash.new do |(k, v), h| h[k] = v end

или, если вы ленивый поклонник неработающего функционального программирования:

h = a.lazy.each_slice( 2 ).tap { |a|
  break Hash.new { |h, k| h[k] = a.find { |e, _| e == k }[1] }
}
#=> {}
h["item 1"] #=> "item 2"
h["item 3"] #=> "item 4"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...