php小編新一為您介紹如何在時間範圍內標準化陣列的元素。在開發中,我們經常需要處理時間序列數據,而這些數據可能會出現時間跳躍或缺失的情況。為了確保資料的準確性和完整性,我們需要對數組中的元素進行標準化。標準化可以使陣列的元素按照時間順序排列,並填滿缺少的時間點。下面,我們將詳細介紹如何實現這項功能。
我正在嘗試標準化一個時間範圍內的元素陣列。假設您有 20 筆銀行交易發生在 2022 年 1 月 1 日
transaction 1 - 2022/01/01 transaction 2 - 2022/01/01 ... transaction 20 - 2022/01/01
除了它們發生的日期之外,我們沒有其他數據,但我們仍然希望為它們分配一天中的一個小時,因此它們結束為:
transaction 1 - 2022/01/01 00:00 transaction 2 - 2022/01/01 ??:?? ... transaction 20 - 2022/01/01 23:59
在 go 中,我有一個函數嘗試計算元素數組中索引的一天中某個時間的標準化:
func normal(start, end time.time, arraysize, index float64) time.time { delta := end.sub(start) minutes := delta.minutes() duration := minutes * ((index+1) / arraysize) return start.add(time.duration(duration) * time.minute) }
但是,我在2022/1/1 00:00 到2022/1/1 23:59 的時間範圍內意外計算出4 個元素數組中索引0 的2022/1/1 05:59 ,相反,我希望看到2022/1/1 00:00。在這些條件下唯一能正常運作的是索引 3。
那麼,我的標準化做錯了什麼?
這是由 @icza 修復的函數
func timeindex(min, max time.time, entries, position float64) time.time { delta := max.sub(min) minutes := delta.minutes() if position < 0 { position = 0 } duration := (minutes * (position / (entries - 1))) return min.add(time.duration(duration) * time.minute) }
有一個例子:假設我們的開始和結束日期是2022/01/01 00:00
- 2022/01/01 00:03
,我們的銀行交易數組中有3 個條目,我們希望取得第3 號交易的標準化時間(數組中的2
):
result := timeindex(time.date(2022, time.january, 1, 0, 0, 0, 0, time.utc), time.date(2022, time.january, 1, 0, 3, 0, 0, time.utc), 3, 2)
由於開始時間和結束時間之間只有4 分鐘(從00:00
到00:03
),並且想要尋找陣列(大小3
)中最後一個條目(索引2
)的標準化時間,結果應該是:
fmt.Printf("%t", result.Equal(time.Date(2022, time.January, 1, 0, 3, 0, 0, time.UTC)) // prints "true"
或範圍內的最後一分鐘,即 00:03
。
這是一個可重現的範例:https://go.dev/play/p/ezwkqanv1at
在n
點之間有n-1
段。這意味著,如果您想在插值中包含start
和end
,則時間段數(即delta
)為arraysize - 1
。
此外,如果將1
加到index
,則結果不可能是start
(您將跳過00:00
)。
所以正確的演算法是這樣的:
func normal(start, end time.time, arraysize, index float64) time.time { minutes := end.sub(start).minutes() duration := minutes * (index / (arraysize - 1)) return start.add(time.duration(duration) * time.minute) }
在 go playground 上嘗試。
另請注意,如果您有很多交易(按照一天中的分鐘數排列,大約一千次),您可能很容易最終會出現多個具有相同時間戳(相同小時和分鐘)的交易。如果您想避免這種情況,請使用比分鐘更小的精度,例如秒或毫秒:
func normal(start, end time.time, arraysize, index float64) time.time { sec := end.sub(start).seconds() duration := sec * (index / (arraysize - 1)) return start.add(time.duration(duration) * time.second) }
是的,這將導致時間戳的秒數也不一定為零,但將確保更高的交易數量具有不同的、唯一的時間戳。
如果您的交易數量級接近一天的秒數(即 86400),那麼您可以完全刪除此「單位」並使用 time.duration
本身(即奈秒)。即使對於最大數量的事務,這也將保證時間戳的唯一性:
func normal(start, end time.time, arraysize, index float64) time.time { delta := float64(end.sub(start)) duration := delta * (index / (arraysize - 1)) return start.add(time.duration(duration)) }
用 100 萬筆交易對此進行測試,以下是前 15 個時間部分(它們僅在亞秒部分延遲):
0 - 00:00:00.00000 1 - 00:00:00.08634 2 - 00:00:00.17268 3 - 00:00:00.25902 4 - 00:00:00.34536 5 - 00:00:00.43170 6 - 00:00:00.51804 7 - 00:00:00.60438 8 - 00:00:00.69072 9 - 00:00:00.77706 10 - 00:00:00.86340 11 - 00:00:00.94974 12 - 00:00:01.03608 13 - 00:00:01.12242 14 - 00:00:01.20876 15 - 00:00:01.29510 16 - 00:00:01.38144 17 - 00:00:01.46778 18 - 00:00:01.55412 19 - 00:00:01.64046
在 go playground 上嘗試這個。
以上是如何標準化時間範圍內數組的元素?的詳細內容。更多資訊請關注PHP中文網其他相關文章!