Учитывая хэш массивов, как создать массив хешей с каждой возможной комбо - PullRequest
0 голосов
/ 10 октября 2018

При наличии хэша со значениями, содержащими массивы неравной длины,

{a: [1, 2, 3], b: [1, 2], c: [1]}

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

[
  {a: 1, b: 1, c: 1},
  {a: 1, b: 2, c: 1},
  {a: 2, b: 1, c: 1},
  {a: 2, b: 2, c: 1},
  {a: 3, b: 2, c: 1},
  {a: 3, b: 2, c: 1}
]

Мы выполняем это, используя вложенные циклы each для каждого ключа, но это выглядит неприятно в большом масштабе.Фактические данные содержат еще много ключей.

Ответы [ 3 ]

0 голосов
/ 11 октября 2018

Есть много способов сделать это.Лично мне нравится решение @Marcin Kołodziej для компактности и эффективности, однако оно может показаться немного загадочным для новичков.

Другой способ решить его - вручную выполнить итерацию по хешу и создать массив:

hash = { a: [1, 2, 3], b: [1, 2], c: [1] }
out = []

hash.each do |key, values|
  if out.empty?
    out = values.map { |v| { key => v } }
  else
    new_out = []
    out.each do |o|
      new_out += values.map { |v| o.merge(key => v) }
    end
    out = new_out
  end
end

out

# [{:a=>1, :b=>1, :c=>1}, {:a=>1, :b=>2, :c=>1}, {:a=>2, :b=>1, :c=>1}, {:a=>2, :b=>2, :c=>1}, {:a=>3, :b=>1, :c=>1}, {:a=>3, :b=>2, :c=>1}] 
0 голосов
/ 11 октября 2018
h = { a:[1,2,3], b:[1,2], c: [1] }

first, *rest = h.map { |k,v| [k].product(v) }
  #=> [[[:a, 1], [:a, 2], [:a, 3]], [[:b, 1], [:b, 2]], [[:c, 1]]]
first.product(*rest).map(&:to_h)
  #=> [{:a=>1, :b=>1, :c=>1}, {:a=>1, :b=>2, :c=>1}, {:a=>2, :b=>1, :c=>1},
  #    {:a=>2, :b=>2, :c=>1}, {:a=>3, :b=>1, :c=>1}, {:a=>3, :b=>2, :c=>1}]

Обратите внимание на промежуточный расчет на втором шаге:

first.product(*rest)
  #=> [[[:a, 1], [:b, 1], [:c, 1]],
  #    [[:a, 1], [:b, 2], [:c, 1]],
  #    [[:a, 2], [:b, 1], [:c, 1]],
  #    [[:a, 2], [:b, 2], [:c, 1]],
  #    [[:a, 3], [:b, 1], [:c, 1]],
  #    [[:a, 3], [:b, 2], [:c, 1]]]
0 голосов
/ 11 октября 2018
keys = hash.keys
hash.values.inject(:product).map do |p|
  Hash[keys.zip(p.flatten)]
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...