我正在嘗試為作業面試完成基于專案的評估,他們只在 Ruby on Rails 中提供它,我對此知之甚少。我正在嘗試獲取一個包含兩個或多個陣列散列的散列,并將這些陣列組合成一個散列陣列,同時消除基于“id”:值對的重復散列。
所以我試圖接受這個:
h = {
'first' =>
[
{ 'authorId' => 12, 'id' => 2, 'likes' => 469 },
{ 'authorId' => 5, 'id' => 8, 'likes' => 735 },
{ 'authorId' => 8, 'id' => 10, 'likes' => 853 }
],
'second' =>
[
{ 'authorId' => 9, 'id' => 1, 'likes' => 960 },
{ 'authorId' => 12, 'id' => 2, 'likes' => 469 },
{ 'authorId' => 8, 'id' => 4, 'likes' => 728 }
]
}
并把它變成這樣:
[
{ 'authorId' => 12, 'id' => 2, 'likes' => 469 },
{ 'authorId' => 5, 'id' => 8, 'likes' => 735 },
{ 'authorId' => 8, 'id' => 10, 'likes' => 853 },
{ 'authorId' => 9, 'id' => 1, 'likes' => 960 },
{ 'authorId' => 8, 'id' => 4, 'likes' => 728 }
]
uj5u.com熱心網友回復:
Ruby 有很多方法可以實作這一點。
我的第一直覺是按id
它對它們進行分組,然后從陣列中只選擇第一項。
h.values.flatten.group_by{|x| x["id"]}.map{|k,v| v[0]}
更簡潔的方法是在展平哈希陣列后根據 id 選擇不同的專案,這就是Cary Swoveland在評論中建議的
h.values.flatten.uniq { |h| h['id'] }
uj5u.com熱心網友回復:
TL;博士
適合您發布的資料的問題的最簡單解決方案是h.values.flatten.uniq
. 您可以在此處停止閱讀,除非您想了解為什么您不需要關心此特定資料集的重復 ID,或者您何時可能需要關心以及為什么這通常不像看起來那么簡單。
在接近尾聲時,我還提到了 Rails 的一些特性,這些特性解決了您不需要處理這些特定資料的邊緣情況。但是,它們可能有助于其他用例。
跳過特定于 ID 的重復資料洗掉;而是專注于洗掉重復的哈希
首先,您沒有id
不屬于重復 Hash 物件的重復鍵。盡管 Ruby 實作保留了 Hash 物件的入口順序,但 Hash 在概念上是無序的。實際上,這意味著具有相同鍵和值的兩個 Hash 物件(即使它們處于不同的插入順序)仍然被認為是相等的。所以,也許不直觀:
{'authorId' => 12, 'id' => 2, 'likes' => 469} ==
{'id' => 2, 'likes' => 469, 'authorId' => 12}
#=> true
鑒于您的示例輸入,您實際上不必擔心此練習的唯一 ID。您只需要從合并的 Array 中消除重復的 Hash 物件,而您只有其中一個。
duplicate_ids =
h.values.flatten.group_by { _1['id'] }
.reject { _2.one? }.keys
#=> [2]
unique_hashes_with_duplicate_ids =
h.values.flatten.group_by { _1['id'] }
.reject { _2.uniq.one? }.count
#=> 0
如您所見,'id' => 2
是在兩個 Hash 值中找到的唯一 ID,盡管在相同的 Hash 物件中。由于您只有一個重復的 Hash,因此問題已簡化為展平存盤在h中的 Hash 值陣列,以便您可以從組合 Array 中洗掉任何重復的 Hash 元素(而不是重復的 ID)。
已發布問題的解決方案
可能存在需要處理哈希鍵唯一性的用例,但這不是其中之一。除非您想按某個鍵對結果進行排序,否則您真正需要的是:
h.values.flatten.uniq
由于沒有要求您對合并陣列中的 Hash 物件進行排序,因此您可以避免需要另一個方法呼叫(在這種情況下,無論如何)是無操作的。
“獨特性”在沒有附加背景的情況下可能會很棘手
查看id
密鑰的唯一原因是,如果您在多個唯一Hash 物件中有重復的 ID,如果是這種情況,您將不得不擔心要保留哪個 Hash 是正確的。例如,給定:
[ {'id' => 1, 'authorId' => 9, 'likes' => 1_920},
{'id' => 1, 'authorId' => 9, 'likes' => 960} ]
這些記錄中的哪一項是“重復”的?如果沒有時間戳等其他資料,簡單地鏈接uniq { h['id' }
或合并 Hash 物件將分別為您提供第一條或最后一條記錄。考慮:
[
{'id' => 1, 'authorId' => 9, 'likes' => 1_920},
{'id' => 1, 'authorId' => 9, 'likes' => 960}
].uniq { _1['id'] }
#=> [{"id"=>1, "authorId"=>9, "likes"=>1920}]
[
{'id' => 1, 'authorId' => 9, 'likes' => 1_920},
{'id' => 1, 'authorId' => 9, 'likes' => 960}
].reduce({}, :merge)
#=> {"id"=>1, "authorId"=>9, "likes"=>960}
利用像 Rails 特定的時間戳功能一樣的背景關系
雖然上面描述的唯一性問題似乎超出了您當前被問到的問題的范圍,但了解任何型別的資料轉換的局限性都是有用的。此外,了解 Ruby on Rails 支持ActiveRecord::Timestamp以及在資料庫遷移中創建和管理與時間戳相關的列可能在更廣泛的意義上是高度相關的。
你不需要知道這些事情來回答最初的問題。但是,了解給定解決方案何時適合特定用例以及何時不適合也很重要。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/484997.html