[英]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.