Не очень симпатично с несколькими скобками в блоке, но это делает только одну итерацию api_response.

я есть массив хэшей, представляющих объекты в ответ на вызов API. Мне нужно извлечь данные из некоторых хешей, и один конкретный ключ служит идентификатором для хеш-объекта. Я хотел бы преобразовать массив в хеш с ключами в качестве идентификаторов, а значения в качестве исходного хеша с этим идентификатором.

Вот о чем я говорю:

api_response = [
  { :id => 1, :foo => 'bar' },
  { :id => 2, :foo => 'another bar' },
  # ..
]

ideal_response = {
  1 => { :id => 1, :foo => 'bar' },
  2 => { :id => 2, :foo => 'another bar' },
  # ..
}

Есть два способа сделать это.

Сопоставьте данные сideal_response (ниже)использованиеapi_response.find { |x| x[:id] == i } для каждой записи мне нужно получить доступ.Метод, о котором я не знаю, возможно, включающий способ использованияmap построить хэш, изначально.

Мой метод картирования:

keys = data.map { |x| x[:id] }
mapped = Hash[*keys.zip(data).flatten]

Я не могу не чувствовать, что есть более эффективный и аккуратный способ сделать это. Вариант 2 очень эффективен, когда требуется минимальное количество записей, к которым необходимо получить доступ. Сопоставление здесь превосходно, но оно начинает разрушаться, когда в ответе много записей. К счастью, я не ожидаю, что будет более 50-100 записей, поэтому достаточно картографирования.

Есть ли более умный, аккуратный или более эффективный способ сделать это в Ruby?

Ответы на вопрос(1)

Решение Вопроса

Ruby <= 2.0

# {1=>{:id=>1, :foo=>"bar"}, 2=>{:id=>2, :foo=>"another bar"}} 

Тем не мение,Hash :: [] довольно некрасиво и нарушает обычный поток ООП слева направо. Вот почемуГрани предложилПеречислимых # затор:

require 'facets'
api_response.mash { |r| [r[:id], r] }
# {1=>{:id=>1, :foo=>"bar"}, 2=>{:id=>2, :foo=>"another bar"}} 

Эту базовую абстракцию (преобразование перечислимых в хэши) давно просили включить в Ruby, увы,без удачи.

Ruby> = 2.1

[ОБНОВИТЬ] Все еще нет любви кEnumerable#mash, но теперь у нас естьМассив # to_h, Не идеально, потому что нам нужен промежуточный массив, но лучше, чем ничего:

# ruby 2.1
api_response.map { |r| [r[:id], r] }.to_h

Ваш ответ на вопрос