#ruby
#ruby
Вопрос:
Имея два массива разного размера, я хотел бы получить longer
массив в виде ключей, а shorter
один — в виде значений. Однако я не хочу, чтобы какие-либо ключи оставались пустыми, поэтому мне нужно продолжать выполнять итерации по shorter
массиву, пока все ключи не получат значение.
РЕДАКТИРОВАТЬ: я хочу, чтобы массив дольше оставался нетронутым, но без пустых значений, это означает, что продолжайте выполнять итерации по более коротким, пока все ключи не получат значение.
longer = [1, 2, 3, 4, 5, 6, 7]
shorter = ['a', 'b', 'c']
Hash[longer.zip(shorter)]
#=> {1=>"a", 2=>"b", 3=>"c", 4=>nil, 5=>nil, 6=>nil, 7=>nil}
Ожидаемый результат
#=> {1=>"a", 2=>"b", 3=>"c", 4=>"a", 5=>"b", 6=>"c", 7=>"a"}
Комментарии:
1. Опубликуйте ожидаемый результат.
2.
longer.each_with_object({}).with_index { |(x,hsh),i| hsh[x] = shorter[i % shorter.size] } #=> {1=>"a", 2=>"b", 3=>"c", 4=>"a", 5=>"b", 6=>"c", 7=>"a"}
Ответ №1:
Вот элегантный вариант. Вы можете «зациклить» короткий массив
longer = [1, 2, 3, 4, 5, 6, 7]
shorter = ['a', 'b', 'c']
longer.zip(shorter.cycle).to_h # => {1=>"a", 2=>"b", 3=>"c", 4=>"a", 5=>"b", 6=>"c", 7=>"a"}
Комментарии:
1. @AndreyDeineko: много переполнения стека 🙂
2. Аккуратно!! Вообще не знал о цикле : O
3. Я вижу все эти ответы и понимаю, что я бы тоже начал думать о некоторых
each_with_object
/inject
вещах.. я учусь, учусь и еще раз учусь4. @AndreyDeineko:
each_with_object
это мой инструмент для перехода. это швейцарский армейский нож перечислимой обработки 🙂5. @CarySwoveland: о, прекрати это, ты 🙂
Ответ №2:
Грубый способ, пока вы не найдете что-то более элегантное: нарежьте более длинный массив в соответствии с длиной более короткого и выполните итерацию по нему, чтобы повторно отобразить значения.
mapped = longer.each_slice(shorter.length).to_a.map do |slice|
Hash[slice.zip(shorter)]
end
=> [{1=>"a", 2=>"b", 3=>"c"}, {4=>"a", 5=>"b", 6=>"c"}, {7=>"a"}]
Объедините все хэши внутри отображенного массива в один хэш
final = mapped.reduce Hash.new, :merge
=> {1=>"a", 2=>"b", 3=>"c", 4=>"a", 5=>"b", 6=>"c", 7=>"a"}
Комментарии:
1. Что ж, я просто оставлю это здесь для альтернативного (более длительного) подхода. Ответ Серджио — лучший способ добиться этого.
2. По крайней мере, вы были первым, кто понял намерения операционной системы.
3. @sagarpandya82 😉 Спасибо, что заметили, что
Ответ №3:
Вот забавный ответ.
longer = [1, 2, 3, 4, 5, 6, 7]
shorter = ['a', 'b', 'c']
h = Hash.new do |h,k|
idx = longer.index(k)
idx ? shorter[idx % shorter.size] : nil
end
#=> {}
h[1] #=> a
h[2] #=> b
h[3] #=> c
h[4] #=> a
h[5] #=> b
h[6] #=> c
h[7] #=> a
h[8] #=> nil
h #=> {}
h.values_at(3,5) #=> ["c", "b"]
Если этого недостаточно (например, если вы хотите использовать Hash
такие методы, как keys
, key?
, merge
, to_a
и т.д.), вы могли бы довольно легко создать связанный хэш:
longer.each { |n| h[n] = h[n] }
h #=> {1=>"a", 2=>"b", 3=>"c", 4=>"a", 5=>"b", 6=>"c", 7=>"a"}