我有以下資料集:
{
Nov 2020=>1,
Dec 2020=>2,
Jan 2021=>3,
Feb 2021=>4,
Mar 2021=>5,
Apr 2021=>6
}
使用以下代碼:
cumulative_count = 0
count_data = {}
data_set.each { |k, v| count_data[k] = (cumulative_count = v) }
我正在生成以下資料集:
{
Nov 2020=>1,
Dec 2020=>3,
Jan 2021=>6,
Feb 2021=>10,
Mar 2021=>15,
Apr 2021=>21
}
即使我有each單行,我覺得必須有某種方法可以將整個事情作為單行來完成。我試過使用inject沒有運氣。
uj5u.com熱心網友回復:
這可以解決問題:
input.each_with_object([]) { |(key, value), arr| arr << [key, arr.empty? ? value : value arr.last[1]] }.to_h
=> {"Nov 2020"=>1, "Dec 2020"=>3, "Jan 2021"=>6, "Feb 2021"=>10, "Mar 2021"=>15, "Apr 2021"=>21}
對于定義為的輸入:
input = {
'Nov 2020' => 1,
'Dec 2020' => 2,
'Jan 2021' => 3,
'Feb 2021' => 4,
'Mar 2021' => 5,
'Apr 2021' => 6
}
這個想法是注入一個陣列(通過each_with_object)來保存處理過的資料,并允許我們輕松獲取前一對的值,從而允許我們累積值。最后,我們將這個陣列轉換為一個散列,這樣我們就有了我們想要的資料結構。
只是添加一個免責宣告,因為正在處理的資料是一個哈希(因此不是一個保留順序的資料結構),一個完整的單線考慮也忽略任何可能的排序的哈希將如下:
input.to_a.sort_by { |pair| Date.parse(pair[0]) }.each_with_object([]) { |pair, arr| arr << [pair[0], arr.empty? ? pair[1] : pair[1] arr.last[1]] }.to_h
=> {"Nov 2020"=>1, "Dec 2020"=>3, "Jan 2021"=>6, "Feb 2021"=>10, "Mar 2021"=>15, "Apr 2021"=>21}
在這種情況下,我們應用相同的想法,但首先將原始資料按日期轉換為有序陣列。
uj5u.com熱心網友回復:
input = {
'Nov 2020' => 1,
'Dec 2020' => 2,
'Jan 2021' => 3,
'Feb 2021' => 4,
'Mar 2021' => 5,
'Apr 2021' => 6
}
如果它必須在一個物理行上,并且允許使用分號:
t = 0; input.each_with_object({}) { |(k, v), a| t = v; a[k] = t }
如果它必須在一個物理行上,并且不允許使用分號:
input.each_with_object({ t: 0, data: {}}) { |(k, v), a| (a[:t] = v) and (a[:data][k] = a[:t]) }[:data]
但在實際實踐中,我認為在多條物理線路上更容易閱讀:)
t = 0
input.each_with_object({}) { |(k, v), a|
t = v
a[k] = t
}
uj5u.com熱心網友回復:
TL;博士
這就是我最終得到的結果:
input.each_with_object({}) { |(k, v), h| h[k] = v h.values.last.to_i }
向Marcos Parreiras(公認的答案)致敬,因為他指出了我的方向each_with_object和想法,即拉出最后一個值進行累積,而不是使用 =初始化為 0 的累積變數。
細節
我最終得到了 3 個潛在的解決方案(如下所列)。我的原始代碼加上兩個選項each_with_object,其中一個取決于陣列,另一個取決于哈希。
原版的
cumulative_count = 0
count_data = {}
input.each { |k, v| count_data[k] = (cumulative_count = v) }
使用陣列
input.each_with_object([]) { |(k, v), a| a << [k, v a.last&.last.to_i] }.to_h
使用哈希
input.each_with_object({}) { |(k, v), h| h[k] = v h.values.last.to_i }
我選擇了使用哈希的選項,因為我認為它是最干凈的。但是,值得注意的是,它并不是性能最高的。純粹基于性能,最初的解決方案是毫無疑問的贏家。自然,它們都非常快,所以為了真正看到性能差異,我必須多次運行這些選項(如下所示)。但由于我的實際解決方案一次只能在生產中運行一次,所以我決定在納秒級的性能上保持簡潔。:-)
表現
每個解決方案都在2_000_000.times { }.
原版的
#<Benchmark::Tms:0x00007fde00fb72d8 @real=2.5452079999959096, @stime=0.09558999999999962, @total=2.5108440000000005, @utime=2.415254000000001>
使用陣列
#<Benchmark::Tms:0x00007fde0a1f58e8 @real=7.3623509999597445, @stime=0.08986500000000053, @total=7.250730000000002, @utime=7.160865000000001>
使用哈希
#<Benchmark::Tms:0x00007f9e19ca7678 @real=5.903417999972589, @stime=0.057482000000000255, @total=5.830285999999999, @utime=5.772803999999999>
uj5u.com熱心網友回復:
input = {
'Nov 2020' => 1,
'Dec 2020' => 2,
'Jan 2021' => 3,
'Feb 2021' => 4,
'Mar 2021' => 5,
'Apr 2021' => 6
}
如果,如示例中所示,值從第一個值開始1并且第一個值之后的每個值都1大于前一個值(在哈希中保證鍵/值插入順序),則該值n將轉換為1 2 ... n,它是算術級數,等于以下。
input.transform_values { |v| (1 v)*v/2 }
#=> {"Nov 2020"=>1, "Dec 2020"=>3, "Jan 2021"=>6, "Feb 2021"=>10,
# "Mar 2021"=>15, "Apr 2021"=>21}
請注意,這不需要Hash#transform_values以任何特定順序處理鍵值對。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/456264.html
上一篇:在Mac上使用不同的應用程式分別設定ruby??版本
下一篇:Ruby_如何在哈希中查找值訂閱
