Перевести Ruby хеш (ключ, значение) в отдельные ключи - PullRequest
0 голосов
/ 18 января 2019

У меня есть функция карты в ruby, которая возвращает массив массивов с двумя значениями в каждом, которые я хочу иметь в другом формате.

Что я хочу иметь:

"countries": [
  {
     "country": "Canada",
     "count": 12
   },
   {and so on... }
]

Но карта, очевидно, возвращает мои значения в виде массива:

"countries": [
    [
        "Canada",
        2
    ],
    [
        "Chile",
        1
    ],
    [
        "China",
        1
    ]
]

При использовании Array :: to_h я также могу приблизить его к формату, который я на самом деле хочу иметь.

"countries": {
    "Canada": 2,
    "Chile": 1,
    "China": 1,
}

Я пытался уменьшить / ввести, each_with_object, но в обоих случаях я не понимаю, как получить доступ к входящим параметрам. При поиске здесь вы найдете много похожих проблем. Но не нашел способа адаптировать их к моему делу. Надеюсь, что вы можете помочь найти краткое и элегантное решение.

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Просто из любопытства:

countries = [['Canada', 2], ['Chile', 1], ['China', 1]]
countries.map(&%i[country count].method(:zip)).map(&:to_h)
#⇒ [{:country=>"Canada", :count=>2},
#   {:country=>"Chile", :count=>1},
#   {:country=>"China", :count=>1}]
0 голосов
/ 18 января 2019

Вам даны два массива:

countries= [['Canada', 2], ['Chile', 1], ['China', 1]]
keys = [:country, :count]

Вы могли бы написать

[keys].product(countries).map { |arr| arr.transpose.to_h }
  #=> [{:country=>"Canada", :count=>2},
  #    {:country=>"Chile", :count=>1},
  #    {:country=>"China", :count=>1}]

или просто

countries.map { |country, cnt| { country: country, count: cnt } }
  #=> [{:country=>"Canada", :count=>2},
  #    {:country=>"Chile", :count=>1},
  #    {:country=>"China", :count=>1}]

но первое имеет преимущество в том, что не нужно менять код в именах смен ключей. На самом деле, не было бы необходимости менять код, если изменились массивы countries и keys, при условии countries[i].size == keys.size для всех i = 0..countries.size-1. (См. Пример в конце.)

Первоначальный шаг для первого расчета выглядит следующим образом.

a = [keys].product(countries)
  #=> [[[:country, :count], ["Canada", 2]],
  #    [[:country, :count], ["Chile", 1]],
  #    [[:country, :count], ["China", 1]]] 

См. Массив # product . Теперь у нас есть

a.map { |arr| arr.transpose.to_h }

map передает первый элемент a в блок и устанавливает переменную блока arr в это значение:

arr = a.first
  #=> [[:country, :count], ["Canada", 2]]

Затем выполняется расчет блока:

b = arr.transpose
  #=> [[:country, "Canada"], [:count, 2]] 
b.to_h
  #=> {:country=>"Canada", :count=>2}

Итак, мы видим, что a[0] (arr) отображается на {:country=>"Canada", :count=>2}. Следующие два элемента a затем передаются в блок и выполняются аналогичные вычисления, после чего map возвращает требуемый массив из трех хешей. См. Array # transpose и Array # to_h .

Вот второй пример с использованием того же кода.

countries= [['Canada', 2, 9.09], ['Chile', 1, 0.74],
            ['China', 1, 9.33], ['France', 1, 0.55]]

keys = [:country, :count, :area]

[keys].product(countries).map { |arr| arr.transpose.to_h }
  #=> [{:country=>"Canada", :count=>2, :area=>9.09},
  #    {:country=>"Chile", :count=>1, :area=>0.74},
  #    {:country=>"China", :count=>1, :area=>9.33},
  #    {:country=>"France", :count=>1, :area=>0.55}]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...