簡體   English   中英

將Ruby數組元素轉換為帶索引的哈希計數

[英]Convert Ruby array of elements to Hash of counts with indices

給定Ruby中的二維數組:

[ [1, 1, 1],
  [1, 1],
  [1, 1, 1, 1],
  [1, 1]
]

我想創建一個Hash,其中鍵是每個內部數組的計數,值是原始數組的索引數組,其內部數組大小具有特定計數。 由此產生的哈希將是:

{ 2 => [1, 3], 3 => [0], 4 => [2] }

我如何在Ruby中以簡潔的方式表達這一功能? 我正在嘗試類似於Hash.new([]).tap { |h| array.each_with_index { |a, i| h[a.length] << i } } Hash.new([]).tap { |h| array.each_with_index { |a, i| h[a.length] << i } } Hash.new([]).tap { |h| array.each_with_index { |a, i| h[a.length] << i } } ,但生成的Hash為空。

您的代碼有兩個問題。 第一個是當h為空並且你寫,例如, h[2] << 1 ,因為h沒有鍵2h[2]返回默認值,所以這個表達式變為[] << 1 #=> [1] ,但[1]未附加到散列,因此不添加任何鍵和值。

你需要寫h[2] = h[2] << 1 1 如果你這樣做,你的代碼返回h #=> {3=>[0, 1, 2, 3], 2=>[0, 1, 2, 3], 4=>[0, 1, 2, 3]} 不幸的是,這仍然是不正確的,這將我們帶到您的代碼的第二個問題:您沒有正確定義新創建的哈希的默認值。

首先要注意的是

h[3].object_id
  #=> 70113420279440 
h[2].object_id
  #=> 70113420279440 
h[4].object_id
  #=> 70113420279440 

啊哈,這三個值都是同一個對象! h沒有密鑰k時, h[k]返回new的參數[] 的問題是,是相同的數組返回所有密鑰k添加到哈希,所以你會增加一個鍵-值對為空數組的第一個新的密鑰,然后將第二鍵值對到該相同的下一個新鍵的數組,依此類推。 請參閱下文,了解如何定義哈希。

通過這兩個更改,您的代碼可以正常工作,但我建議您按如下方式編寫代碼。

arr = [ [1, 1, 1], [1, 1], [1, 1, 1, 1], [1, 1] ]

arr.each_with_index.with_object(Hash.new {|h,k| h[k]=[]}) { |(a,i),h|
  h[a.size] << i }
  #=> {3=>[0], 2=>[1, 3], 4=>[2]} 

它使用Hash :: new的形式,它使用一個塊來計算哈希的默認值 (即當哈希h沒有密鑰k時由h[k]返回的值),

要么

arr.each_with_index.with_object({}) { |(a,i),h| (h[a.size] ||= []) << i }
  #=> {3=>[0], 2=>[1, 3], 4=>[2]} 

這兩者實際上有以下幾點:

h = {}
arr.each_with_index do |a,i|
  sz = a.size
  h[sz] = [] unless h.key?(sz)
  h[a.size] << i
end
h #=> {3=>[0], 2=>[1, 3], 4=>[2]} 

另一種方法是在獲取每個內部數組的索引后,使用Enumerable#group_by ,對數組大小進行分組。

h = arr.each_with_index.group_by { |a,i| a.size }
  #=> {3=>[[[1, 1, 1], 0]],
  #    2=>[[[1, 1], 1], [[1, 1], 3]],
  #    4=>[[[1, 1, 1, 1], 2]]} 
h.each_key { |k| h[k] = h[k].map(&:last) }
  #=> {3=>[0], 2=>[1, 3], 4=>[2]}

1表達式h[2] = h[2] << 1使用方法Hash#[] =Hash#[] ,這就是=左邊的h[2]不返回默認值的原因。 或者,該表達式可以寫成h[2] ||= [] << 1

arry = [ [1, 1, 1],
         [1, 1],
         [1, 1, 1, 1],
         [1, 1]
       ]

h = {}
arry.each_with_index do |el,i|
  c = el.count
  h.has_key?(c) ? h[c] << i : h[c] = [i]
end

p h

這會給你

{3=>[0], 2=>[1, 3], 4=>[2]}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM