[英]Map two arrays by index
我有以下数组:
arr1 = [1, 2, 3, 4]
arr2 = [a, b, a, c]
我想要以下输出:
out = {'a' => [1, 3], 'b'=> [2], 'c' => [4]}
在 Ruby 中是否有一种简便的方法可以做到这一点? 目前,我正在使用循环和索引来创建哈希。
您可以编写以下内容。
arr1 = [1, 2, 3, 4]
arr2 = ['a', 'b', 'a', 'c']
arr1.zip(arr2).each_with_object(Hash.new { |h,k| h[k] = [] }) do |(n,c),h|
h[c] << n
end
#=> {"a"=>[1, 3], "b"=>[2], "c"=>[4]}
让我从一个简单的过程方法开始解释这个表达式,然后通过几个步骤来改进代码。
首先创建一个空散列,它将成为您想要的返回值:
h = {}
然后我们可以写如下
(0..arr1.size - 1).each do |i|
n = arr1[i]
c = arr2[i]
h[c] = [] unless h.key?(c)
h[c] << n
end
h #=>{"a"=>[1, 3], "b"=>[2], "c"=>[4]}
它更像 Ruby,但是迭代来自arr1
和arr2
相应值对,即[1, 'a']
、 [2, 'b']
等等。 为此,我们使用方法Array#zip :
pairs = arr1.zip(arr2)
#=> [[1, "a"], [2, "b"], [3, "a"], [4, "c"]]
然后
h = {}
pairs.each do |pair|
n = pair.first
c = pair.last
h[c] = [] unless h.key?(c)
h[c] << n
end
h #=> {"a"=>[1, 3], "b"=>[2], "c"=>[4]}
我们可以做的一个小改进是将数组分解应用于pair
:
h = {}
pairs.each do |n,c|
h[c] = [] unless h.key?(c)
h[c] << n
end
h #=> {"a"=>[1, 3], "b"=>[2], "c"=>[4]}
下一个改进是将each
替换为Enumerable#each_with_object以避免在开头使用h = {}
并在结尾使用h
:
pairs.each_with_object({}) do |(n,c),h|
h[c] = [] unless h.key?(c)
h[c] << n
end
#=> {"a"=>[1, 3], "b"=>[2], "c"=>[4]}
请注意我是如何编写块变量的,其中h
保存返回的对象(初始为空的散列)。 这是数组分解的另一个用途。 欲了解更多关于这个问题,看到这个文章。
前面的表达式很好,读起来很好,但经常看到以下调整:
pairs.each_with_object({}) do |(n,c),h|
(h[c] ||= []) << n
end
#=> {"a"=>[1, 3], "b"=>[2], "c"=>[4]}
如果h
没有键c
, h[c]
返回nil
,所以h[c] ||= []
,或h[c] = h[c] || []
h[c] = h[c] || []
,变成h[c] = nil || []
h[c] = nil || []
,因此h[c] = []
,之后h[c] << n
被执行。
没有比前面的表达式更好或更差,您可能还会看到我在开头提供的代码:
arr1.zip(arr2).each_with_object(Hash.new { |h,k| h[k] = [] }) do |(n,c),h|
h[c] << n
end
这里块变量h
被初始化为一个定义的空哈希
h = Hash.new { |h,k| h[k] = [] }
这采用了Hash::new的形式,它接受一个块而没有参数。 当以这种方式定义散列h
,如果h
没有键c
,则执行h[c]
会导致在执行h[c] << n
之前执行h[c] = []
。
arr1 = [1, 2, 3, 4]
arr2 = %w[a b a c] # ["a", "b", "a", "d"]
所以你的第二个数组是一个字符串数组而不是变量
您可以使用group_by和each_with_index枚举器指向您的变量索引并使用第二个数组对其进行分组
arr1.group_by.each_with_index { |_, index| arr2[index] }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.