Heim  >  Artikel  >  Backend-Entwicklung  >  Wie normalisiert man die Elemente eines Arrays innerhalb eines Zeitbereichs?

Wie normalisiert man die Elemente eines Arrays innerhalb eines Zeitbereichs?

PHPz
PHPznach vorne
2024-02-08 21:30:35746Durchsuche

Wie normalisiert man die Elemente eines Arrays innerhalb eines Zeitbereichs?

php-Editor Xinyi stellt Ihnen vor, wie Sie die Elemente eines Arrays innerhalb eines Zeitbereichs standardisieren. In der Entwicklung müssen wir häufig Zeitreihendaten verarbeiten, und diese Daten können Zeitsprünge oder fehlende Situationen aufweisen. Um die Genauigkeit und Vollständigkeit der Daten sicherzustellen, müssen wir die Elemente im Array standardisieren. Durch die Normalisierung werden die Elemente eines Arrays in chronologische Reihenfolge gebracht und fehlende Zeitpunkte ergänzt. Im Folgenden wird detailliert beschrieben, wie diese Funktion implementiert wird.

Frageninhalt

Ich versuche, eine Reihe von Elementen über einen bestimmten Zeitraum zu normalisieren. Nehmen wir an, Sie haben 20 Banktransaktionen, die am 1. Januar 2022 stattgefunden haben

transaction  1 - 2022/01/01
transaction  2 - 2022/01/01
...
transaction 20 - 2022/01/01

Wir haben keine anderen Daten als das Datum, an dem sie auftreten, aber wir möchten ihnen dennoch eine Stunde des Tages zuordnen, sodass sie am Ende wie folgt lauten:

transaction  1 - 2022/01/01 00:00
transaction  2 - 2022/01/01 ??:??
...
transaction 20 - 2022/01/01 23:59

In go habe ich eine Funktion, die versucht, die Normalisierung einer Tageszeit für einen Index in einem Array von Elementen zu berechnen:

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)
}

Allerdings habe ich versehentlich 1.1.2022 05:59 bei Index 0 im 4-Elemente-Array im Zeitbereich von 1.1.2022 00:00 bis 1.1.2022 23:59 berechnet, stattdessen habe ich es erwartet Siehe 01.01.2022 00:00. Der einzige, der unter diesen Bedingungen korrekt funktioniert, ist Index 3.

Was mache ich also falsch mit der Normalisierung?

Herausgeber:

Dies ist die von @icza behobene Funktion

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)
}

Hier ist ein Beispiel: Nehmen wir an, unser Start- und Enddatum ist 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)

Da zwischen Startzeit und Endzeit nur 4 Minuten normalisierter Zeit (von 00:0000:03),并且想要查找数组(大小 3)中最后一个条目(索引 2) liegen, sollte das Ergebnis wie folgt lauten:

fmt.Printf("%t", result.Equal(time.Date(2022, time.January, 1, 0, 3, 0, 0, time.UTC))
// prints "true"

oder die letzte Minute im Bereich, die 00:03 ist.

Hier ist ein reproduzierbares Beispiel: https://go.dev/play/p/ezwkqanv1at

Workaround

ist in n 点之间有 n-1 段。这意味着,如果您想在插值中包含 startend,则时间段数(即 delta)为 arraysize - 1.

Auch, wenn so 1 添加到 index,则结果不可能是 start (您将跳过 00:00).

Der richtige Algorithmus ist also dieser:

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)
}

Probieren Sie es auf dem Go-Spielplatz aus.

Beachten Sie außerdem, dass Sie bei vielen Transaktionen (geordnet nach Tagesminuten, etwa tausend) leicht mehrere Transaktionen mit demselben Zeitstempel (gleiche Stunde und Minute) erhalten können. Wenn Sie dies vermeiden möchten, verwenden Sie eine kleinere Genauigkeit als Minuten, beispielsweise Sekunden oder Millisekunden:

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)
}

Ja, dies führt zu Zeitstempeln mit Sekunden, die auch nicht unbedingt Null sind, stellt aber sicher, dass höhere Transaktionsvolumina unterschiedliche, eindeutige Zeitstempel haben.

Wenn Ihre Transaktionen in der Größenordnung von Sekunden pro Tag liegen (d. h. 86400), können Sie diese „Einheit“ vollständig entfernen und time.duration selbst (d. h. Nanosekunden) verwenden. Dies garantiert die Eindeutigkeit des Zeitstempels selbst für die größte Anzahl von Transaktionen:

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))
}

Um dies mit 1 Million Transaktionen zu testen, sind hier die ersten 15 Zeitteile (sie werden nur im Teilsekundenteil verzögert):

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

Versuchen Sie es auf dem Go-Spielplatz.

Das obige ist der detaillierte Inhalt vonWie normalisiert man die Elemente eines Arrays innerhalb eines Zeitbereichs?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen