Как l oop над двумя массивами и создать карту в Ruby - PullRequest
1 голос
/ 17 января 2020

Я новичок в Ruby и пробую несколько примеров на этой ссылке .

Скажем, у меня есть два массива

Array1: ["square", "circle", "triagle"]

Array2: ["red", "blue"]

Я хочу создать карту, например,

[{:shape=>"square", :color=>"red"}]
[{:shape=>"square", :color=>"blue"}]
[{:shape=>"circle", :color=>"red"}]
[{:shape=>"circle", :color=>"blue"}]
[{:shape=>"triangle", :color=>"red"}]
[{:shape=>"triangle", :color=>"blue"}]

Вот код, который я пробовал.

def processArray6(array1, array2)
    newMap = [array1].map do |entry|
    {
        shape: entry,
        color: "abc" # Should write another for-loop here to loop over array2
    }
    end
end

array1 = ["square", "circle", "triangle"]
array2 = ["red", "blue,"]

p processArray6(array1, array2)

Вывод для приведенного выше кода:

[{:shape=>["square", "circle", "triangle"], :color=>"abc"}]

Я не очень уверен, как l oop по массиву2.

Я из Java фона и все еще пытаюсь понять, как целая карта возвращается из функции и как обрабатывать каждый элемент массива и создавать карту.

Ответы [ 4 ]

5 голосов
/ 17 января 2020

Если вам нужен массив хешей, где каждый ха sh имеет ключи shape и color, тогда вы можете использовать product между массивами1 и массивом2, а затем просто отобразить результат этого:

array1.product(array2).map { |shape, color| { shape: shape, color: color } }
# [{:shape=>"square", :color=>"red"}, {:shape=>"square", :color=>"blue"}, {:shape=>"circle", :color=>"red"}, {:shape=>"circle", :color=>"blue"}, {:shape=>"triagle", :color=>"red"}, {:shape=>"triagle", :color=>"blue"}]
2 голосов
/ 17 января 2020

Array # product обычно используется здесь, но он возвращает массив (из которого построено ha sh), который может потреблять чрезмерный объем памяти, если два массива, продукт которых находится в процессе вычисляются большие. Вот способ получения хэшей без использования product (или создания временного массива другими способами).

keys = [:shape, :color]
arr1 = ["square", "circle", "triangle"]
arr2 = ["red", "blue"]

arr1.each_with_object([]) do |shape, arr|
  arr2.each { |color| arr << keys.zip([shape, color]).to_h }
end
  #=> [{:shape=>"square", :color=>"red"},
  #    {:shape=>"square", :color=>"blue"},
  #    {:shape=>"circle", :color=>"red"},
  #    ...
  #    {:shape=>"triangle", :color=>"blue"}]              

Любопытно, что не существует метода Array, который производит перечислитель, который генерирует элементы в массиве, возвращаемом Array#product. Это достаточно легко сделать. (См. Enumerator :: new .)

class Array
  def product_each(arr)
    Enumerator.new do |y|
      each { |e| arr.each { |f| y << [e,f] } }
    end
  end
end

Затем

enum = arr1.product_each(arr2)
loop { p enum.next }

отображает:

["square", "red"]
["square", "blue"]
["circle", "red"]
["circle", "blue"]
["triangle", "red"]
["triangle", "blue"]

, что позволяет нам вычислять:

arr1.product_each(arr2).map { |pair| keys.zip(pair).to_h }
  #=> [{:shape=>"square", :color=>"red"},
  #    {:shape=>"square", :color=>"blue"},
  #    {:shape=>"circle", :color=>"red"},
  #    ...
  #    {:shape=>"triangle", :color=>"blue"}]              

без создания временного массива.

2 голосов
/ 17 января 2020

Вы хотите вычислить «произведение» двух списков, что на самом деле очень просто, поскольку Ruby имеет функцию product специально для этого:

KEYS = %i[ shape color ]

def all_shape_colors(shapes, colors)
  shapes.product(colors).map do |pair|
    KEYS.zip(pair).to_h
  end
end

zip используется здесь для ввода двух записей в каждой паре.

На практике это выглядит так:

shapes = %w[ square circle triagle ]

colors = %w[ red blue ]

all_shape_colors(shapes, colors)
# => [{:shape=>"square", :color=>"red"}, {:shape=>"square", :color=>"blue"}, {:shape=>"circle", :color=>"red"}, {:shape=>"circle", :color=>"blue"}, {:shape=>"triagle", :color=>"red"}, {:shape=>"triagle", :color=>"blue"}]

Обратите внимание на использование %w[ x y ] вместо [ "x", "y" ] как способ выражения того же массива с более минимальным синтаксисом. %i[ ... ] то же самое, но возвращает массив символов вместо строк.

На самом деле вы можете go еще один здесь и создать очень обобщенный c метод, который делает эту комбинацию для вас на произвольном числе. вещей:

def hash_product(**things)
  keys = things.keys

  things.values.inject do |s, options|
    # Compute product and flatten, necessary for chains > length 2
    s.product(options).map(&:flatten)
  end.map do |set|
    keys.zip(set).to_h
  end
end

Где вы сейчас используете это так:

hash_product(shape: shapes, color: colors)

Это означает, что нет необходимости в фиксированном наборе ключей. Все будет работать:

hash_product(hair: %w[ red blue green ], hat: %w[ white black yellow ], shoes: %w[ orange brown tan])
# => [{:hair=>"red", :hat=>"white", :shoes=>"orange"}, {:hair=>"red", :hat=>"white", :shoes=>"brown"}, ... ]
2 голосов
/ 17 января 2020

Следующий вернет массив хэшей

def processArray6(array1, array2)

array3 = []

array2.each{|color| array1.each{|shape| array3 << {:shape => shape, :color => color}}}

return array3

end


>> processArray6(array1, array2)
=> [{:color=>"red", :shape=>"square"}, {:color=>"red", :shape=>"circle"}, {:color=>"red", :shape=>"triagle"}, {:color=>"blue", :shape=>"square"}, {:color=>"blue", :shape=>"circle"}, {:color=>"blue", :shape=>"triagle"}]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...