-1

我在 ruby​​ 中有一个 map 函数,它返回一个数组数组,每个数组有两个值,我想用不同的格式。

我想拥有的:

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

但是 map 显然将我的值作为数组返回:

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

使用 Array::to_h 时,我还能够使其更接近我真正想要的格式。

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

我尝试过 reduce/inject, each_with_object 但在这两种情况下我都不明白如何访问传入的参数。在这里搜索时,您会发现许多类似的问题。但是还没有找到一种方法来适应我的情况。希望您能帮助找到一个简短而优雅的解决方案。

4

2 回答 2

4

给你两个数组:

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为 all提供i = 0..countries.size-1。(见最后的例子。)

第一次计算的初始步骤如下。

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

请参阅Array#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#transposeArray#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}]
于 2019-01-18T03:17:55.197 回答
0

只是出于好奇:

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}]
于 2019-01-18T06:18:40.733 回答