将 Ruby hash (key,value) 翻译成单独的键
Translate Ruby hash (key,value) to separate keys
我在 ruby 中有一个 map 函数,其中 returns 一个数组数组,每个数组有两个值,我希望它具有不同的格式。
我想要的:
"countries": [
{
"country": "Canada",
"count": 12
},
{and so on... }
]
但显然映射 returns 我的值作为数组:
"countries": [
[
"Canada",
2
],
[
"Chile",
1
],
[
"China",
1
]
]
当使用 Array::to_h 时,我也能够使它更接近我真正想要的格式。
"countries": {
"Canada": 2,
"Chile": 1,
"China": 1,
}
我试过reduce/inject、each_with_object,但在这两种情况下我都不明白如何访问传入参数。在这里搜索时,您会发现许多类似的问题。但是还没有找到一种方法来使它们适应我的情况。
希望您能帮助找到一个简短而优雅的解决方案。
给你两个数组:
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
都更改了,则无需更改代码,前提是所有 i = 0..countries.size-1
都为 countries[i].size == keys.size
。 (见最后的例子。)
第一次计算的初始步骤如下。
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
returns 所需的三个哈希数组。参见 Array#transpose and 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}]
出于好奇:
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}]
我在 ruby 中有一个 map 函数,其中 returns 一个数组数组,每个数组有两个值,我希望它具有不同的格式。
我想要的:
"countries": [
{
"country": "Canada",
"count": 12
},
{and so on... }
]
但显然映射 returns 我的值作为数组:
"countries": [
[
"Canada",
2
],
[
"Chile",
1
],
[
"China",
1
]
]
当使用 Array::to_h 时,我也能够使它更接近我真正想要的格式。
"countries": {
"Canada": 2,
"Chile": 1,
"China": 1,
}
我试过reduce/inject、each_with_object,但在这两种情况下我都不明白如何访问传入参数。在这里搜索时,您会发现许多类似的问题。但是还没有找到一种方法来使它们适应我的情况。 希望您能帮助找到一个简短而优雅的解决方案。
给你两个数组:
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
都更改了,则无需更改代码,前提是所有 i = 0..countries.size-1
都为 countries[i].size == keys.size
。 (见最后的例子。)
第一次计算的初始步骤如下。
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
returns 所需的三个哈希数组。参见 Array#transpose and 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}]
出于好奇:
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}]