Wert am nächsten zur vollen Sekunde

Hallo Forum,
ich habe die Aufgabe ein Java-Programm zu schreiben, welches aus einer CSV-Datei Werte ausließt und in einer Array speichert.
Jetzt komme ich an dieser Stelle nicht weiter:
Es ist eine eine Spalte mit Zeitstempeln vorhanden.
Es soll der Wert herausgesucht werden der jeweils am nächsten zur vollen Sekunde liegt.
Bei der Sekunde 79084, wäre 79083.99795400001 zum Beispiel näher dran an als 79084.007643.
Der Aufzeichnungszeitraum beträgt 36 Sekunden. Es müssten also zum Schluss 36 Werte ausgegeben werden.

Ich bin für jede Hilfe sehr dankbar.:slight_smile:

ganz normale Handarbeit:
zunächst ist CVS auszuklammern, gut dass du das schon nicht im Thementitel hast sondern dich auf das wahre Problem konzentriest

für jeden Eintrag in Java ein Objekt, schlechterdings ein Array, besser ein Objekt einer genau passenden Klasse

der erste Test-Schritt ist, eine bestimmte Sekunde zu nehmen, die Einträge zu durchlaufen, den Eintrag mit minimaler Differenz zu finden,
machbar oder auch schon Problem?

das könnte man nun für alle 36 sec einzeln machen…,
oder einen Schleifendurchlauf intelligenter:
z.B. je Eintrag Abstand zur nächsten Ganzzahl bilden, vom aktuellen + letzten Eintrag denjenigen mit größerer Differenz streichen

Oder etwas konkreter, auch wenn man beim Code etwas “raten” muss, wie das ganze bisher angesetzt ist:

double actualSeconds = 79084;
double optionA = 79083.99795400001;
double optionB = 79084.007643;
double differenceA = Math.abs(optionA - actualSeconds);
double differenceB = Math.abs(optionB - actualSeconds);
if (differenceA < differenceB)
{
    System.out.println("Closer: "+optionA);
}
else
{
    System.out.println("Closer or equal: "+optionB);
}

Ansonsten wären mehr Details (und ggf. Sonderfälle) hilfreich.

Die Gesamtaufgabe ist für mich ziemlich komplex, deshalb habe ich nur diese eine Teilaufgabe beschrieben um nicht für Verwirrung zu sorgen^^
Ich muss eine CSV einlesen in der ca. 4000 Zeilen bzw. Datensätze gespeichert sind. Die Spalte für die Zeitstempel hat also sehr viele Werte mit Bruchteilen einer Sekunde.
Die gesamte Datenmenge soll reduziert werden, und zwar nur auf die Zeilen deren Zeitstempel am nächsten zur vollen Sekunde liegen.
Also sollen quasi aus ca. 4000 Zeilen 36 Zeilen ausgelesen werden.
Es müssten also nicht nur die Zahlen 79083.99795400001 und 79084.007643 verglichen werden, sondern die ganze Spalte.
Ich hoffe es ist so etwas verständlicher geworden:)

für mein Posting zumindest möchte ich behaupten, dies schon voll erfasst zu haben, nix neues dabei,
mehr Code wird kaum wer posten können (von ‚wollen‘ ganz abgesehen),

also jetzt nichts abzuwarten, entweder von dir neues/ Fragen/ Beispielcode bzw. Beispieldaten mit Problemen usw., oder Thema wohl zu Ende :wink:

Grundsätzlich verstehe ich den Code. ich frage mich nur wie ich das Ganze auf ein Array anwenden kann. Der Code bezieht sich ja nur auf die beiden genannten Zahlen und nicht auf die gesamte Spalte.

Meine Überlegung war die gesamte Spalte als double variablen zu speichern und dann irgendie in den oben genannten Code zu integrieren.
double Zeitstempel = Double.parseDouble(Wertefeld[19]);
Das wären die Werte aus der CSV die mit der jeweiligen Sekunde verglichen werden müssen.

es gibt keine Spalte, verabschiede dich davon,
wie gesagt brauchst du eine Liste/ Array von Einträgen/ Zeilen

in jedem Eintrag ist die Zeit natürlich als ein Attribut eingetragen, an einer bestimmten Stelle, richtig,
aber dies als Information des Eintrags betrachten (wie ein Name), nicht als eigenständige Menge der Zeiten


doch wieder ein Schritt zurück und wie schon gewarnt: bevor du überhaupt an komplizierte Dinge denken kannst muss CSV aus dem Blickfeld verschwinden,

lies 5 Zeilen in Datenstrukturen ein und baue an einer zweiten Codestelle eine Ausgabe (System.out.println(), mit Schleife), Ergebnisausgabe in etwa

Anzahl Einträge: 5
1. Eintrag: a, b, c,
2. Eintrag: e, f, g
usw.

musst du jetzt nicht sklavisch nachbauen und hier abliefern, aber solltest du für dich in etwa können,
soweit Verständnis vorhanden? vorher alles andere unmöglich


danach wie gesagt:
nicht mehr erster, sondern zweiter Schritt… : eine bestimmte Sekunde zur Suche nehmen, wie eben etwa 79084,
die Einträge zu durchlaufen, den Eintrag mit minimaler Differenz finden,

dazu kannst du natürlich immer noch fragen ‘und wie geht das’, wo gar nichts ist helfen alle Tipps nicht, nur fertiger Code zur Abgabe…,
aber vorerst noch Hoffnung: bringt dich das weiter?

Die besagte Spalte der CSV habe ich mit folgendem Code in ein Array gespeichert.

double Zeitstempel = Double.parseDouble(Wertefeld[19]);
double[] Zeit = new double[1];
Zeit[1] = Zeitstempel;

Wenn es tatsächlich nur darum ginge aus den beiden Zahlen die nächste zur Zahl 79084 zu finden würde ich das Ganze mit dem oben genannten Code oder so:
if (Math.abs(Zeitstempel1 - Sekunde) < (Math.abs(Zeitstempel2 - Sekunde)
lösen.

Der Grundsatz ist klar denke ich…Ich stehe nur vor dem Problem das ganze nicht für zwei Zahlen sondern bezogen auf das gesamte Array anzuwenden.

ein Array ist automatisch immer mit Schleife zu durchlaufen,
Schleife bewirkt dass du jeweils das aktuelle Element in die Hand bekommst, was du dann ähnlich mit einem Suchwert vergleichen kannst wie einen Einzelwert,
wenn ein aktuelles Element wichtig erscheint, dann in einer Variablen (die außerhalb definiert ist) merken,

das kann dann auch als zweiten Vergleich dienen: ist das aktuelle Schleifenelement besser im Vergleich zum Suchwert als ein gemerktes Element von bisherigem Array-Verlauf?


sagt dir irgendwas davon was? Programmierung kann nicht in so breiter Form im Forum erklärt werden, du müsstest schon irgendwas selber beherrschen

‘java kleinstes element array’ ist eine typische Aufgabe, zu der du in Suchmaschinen Beispiele anschauen kannst,
da ist keine Differenz zu einem Suchwert zu bilden, etwas einfacher aufgebaut, wichtig wiederum vorher zu verstehen

oder allgemein Tutorials/ Lehrbücher, speziell zu Arrays/ Schleifen, vielleicht Beispielanwendungen dabei,

Wie ich den kleinsten Wert in einem Array finden kann weiß ich. In diesem Fall aber macht mir die zweite Variable “Zeitstempel2”
zu schaffen. Ich weiß nicht wie ich diesen Vergleich in eine for Schleife einbauen kann:ka:
Ich habe ein Brett vorm Kopf und würde mich sehr sehr über einen Tipp freuen:idea:

wenn du nach einem Wert 50 suchst und ein Array 45, 56, 53 hast
und in der Schleife zu jedem Element in temporärer Variable die Differenz ausrechnest, also 5, 6, 3,
dann ist dein Problem quasi, als wenn du von 5, 6, 3 das kleineste Element suchen müsstest

   int x = array**
}
-> kleinestes x finden leicht?


vs.

for (...) {
   int x = array** - irgendwas;
}
-> kleinstes x finden auch leicht?

natürlich dann außerhalb der Schleife nicht (nur) die 5, die 6 bzw. die 3 speichern, sondern auch den zugehörigen Wert, z.B. in zwei Variablen,
denn am Ende willst du ja nicht nur ‘3’ wissen, sondern vor allem ‘53’

Als ich sehe in dieser Aufgabe 2 Probleme:

  1. finde alle (ganzen) Sekunden
  2. finde zu jeder (ganzen) Sekunde den nächstgelegenen Wert.

An dieser Stelle würde ich mir eine wichtige Eigenschaft der Zeit zu nutze machen: sie läuft nur in eine Richtung.
Von daher würde ich davon ausgehen, dass die Einträge in der CSV nach der Zeit aufsteigend sortiert sind.

Damit ergibt sich für mich folgende Handlungsanweisung:

[ol]
[li] nimm den ersten Eintrag und bestimme die “ganze Sekunde”
[/li][li] bilde die Differenz zwischen der “ganzen Sekunde” und dem realen Zeitstempel
[/li][li] speichere die Differenz in einer Hilfsvariablen
[/li][li] füge eine neue Instanz der “ganze Sekunde”-Klasse der Ergebnisliste hinzu (Arrays sind erst mal unpraktisch, da die nicht wachsen können…) mit den Werten der ersten Zeile
[/li][li] beginne eine Schleife über alle Einträge des CSV, beginne mit der zweiten Zeile
[/li][li] bilde die Differenz der aktuellen Zeile zur letzten “ganzen Sekunde” in der Ergebnisliste
[/li][li] vergleiche die neue Differenz mit der aus der letzten Iteration
[/li][li] [LIST=a][]wenn die Differenz kleiner wurde:[list=1][] ersetze die Werte im letzten Objekt der Ergebnisliste mit denen der aktuellen Zeile
[/li][li] aktualisiere die Hifsvariable mit der aktuellen Differenz[/ol]
[/li][li]wenn die Differenz größer wurde: [ol][*] erzeuge ein neues “ganze Sekunde”-Objekt für die nächste Sekunde (aktuelle ganze Sekunde+1)
[/li][li]füge es mit den Werten der aktuellen Zeile der Ergebnisliste hinzu.
[/li][li]ermittle die Differenz der neuen “ganzen Sekunde” zum Zeitstempel der aktuellen Zeile
[/li][li]aktualisiere die Hilfsvariable mit der neuen Differenz[/ol]
[/li][/LIST]
[li] wähle die nächste Zeile, falls noch eine übrig ist.
[/li][li] zurück zu 6.
[/li][/LIST]

bye
TT

for(String zeitstempelAusArray : gesamtesArray) {
    if (Math.abs(zeitstempelAusArray - Sekunde) < (Math.abs(aktuellerZeitstempelDerNaeherAnDerSekundeLiegt- Sekunde) {
        aktuellerZeitstempelDerNaeherAnDerSekundeLiegt = zeitstempelAusArray;
    }
}```

Dieser Code müsste funktionieren:)
Allerdings stehe ich jetzt vor dem Problem dass ich aus Wertefeld[18] ein 1D array "extrahieren" muss um diesen Code anzuwenden.
In der Form Wertefeld[18] kann ich das Array nicht verwenden.

die letzten zwei Zeilen sind recht unverständlich und bringt es wieder auf die schon genannte Voraufgabe,
die Daten in einer geeigneten Datenstruktur abzulegen so dass Ausgabe

Anzahl Einträge: 5
1. Eintrag: a, b, c, (evtl. nur Zeitwert)
2. Eintrag: e, f, g
usw.

möglich ist

kannst du das? wie sieht deine Datenstruktur der Daten aus, die du durchlaufen willst?

wenn du nur alle Zeitwerte in ‘gesamtesArray’ ablegen willst, bitte,
oder höhere Einträge, jeder davon ein Array für sich oder ein Objekt mit Attributen, darunter auch der Zeitwert

    if (Math.abs(e.getZeit() - ..

Ich habe mit:
Zeitstempel = Double.parseDouble(Wertefeld[18]);

eine Double Variable mit allen Werten erstellt.
Diese Werte muss ich nun irgendwie in ein Array abspeichern. Also für jeden Wert bzw. Zeitstempel einen “Bereich” im Array.

Das Array muss ich dann noch erstellen.

double[] Zeitstempel = new double[5000];

Ich weiß dass das nicht die eleganteste Methode ist aber ich möchte einfach nur dass das Programm irgendwie richtige Ergebnisse liefert.

Die Beschreibungen sind schon arg konfus. Du musst das ganze ja nicht unbedingt in einen eigenen Array packen. Aber mal von vorne:

Was ist “Wertefeld”?

(ECHTER Code könnte helfen…)

Wichtiger Satz, damit wird es klarer. Lass dich nicht ins Bockshorn jagen.

        for (int x = 0; x < da.length; x++) {
            da[x] = Math.random() * 36;
        }
        Arrays.sort(da);
        int[] indexes = new int[36];
        int j = 0;
        for (int i = 0; i < indexes.length; i++) {
            while (Math.abs(da[j] - i) > Math.abs(da[j + 1] - i)) { // Das hat SlaterB im Vorposting
                j++;
            }
            indexes** = j++;
        }
        for (int i = 0; i < indexes.length; i++) {
            System.out.println(i + " " + indexes** + " " + (int) (da[indexes**] * 100000.0) / 100000.0);
        }```

Damit erhalten wir dann Daten, über welche man kann:


0 0 0.01486
1 105 0.99871
2 203 1.99742
3 300 2.99804
4 423 3.99524
5 539 5.00012
6 677 6.00587
7 800 6.99877
8 894 8.00551
9 1009 8.99902
10 1143 10.00019
11 1264 10.98821
12 1365 11.99965
13 1464 13.00064
14 1572 13.99611
15 1689 14.99783
16 1788 15.99144
17 1907 17.00741
18 2029 17.99835
19 2139 19.00014
20 2244 20.00239
21 2336 21.00063
22 2446 22.00257
23 2581 22.99909
24 2691 24.00855
25 2795 25.00465
26 2918 25.99705
27 3032 26.99889
28 3138 27.9969
29 3234 29.00486
30 3346 29.99615
31 3458 31.01425
32 3570 31.99014
33 3657 33.00387
34 3783 33.99863
35 3896 34.99345



4 423 3.99524 --- ist näher(/am nächsten) an 4,
5 539 5.00012 --- ist näher(/am nächsten) an 5, usw.

Es gibt nur einen "Knackpunkt", mit einer gewissen Wahrscheinlichkeit, tritt eine NullPointerException auf! Wenn 3966 Werte kleiner gleich 34 wären... (Ich meine damit die innere Schleife der For Schleife, könnte zu lange laufen, wenn alle Werte kleiner gleich 0 bis 35 wären...)

wenn WerteFeld die Rohdaten einer Zeile darstellt, der Zeitstempel davon an 19. Stelle (für 19. Spalte),
dann ist double gewonnen, der könnte in ein Array eingefügt werden, denn es sind ja sicher viele Zeilen aus dem CSV, viele WerteFeld-Arrays durchzuarbeiten, auch dafür eine Schleife

double[] Zeitstempel wäre ja ok, wenn alle 1500 gefüllt, darüber dann später die Auswertungsschleife

Genau…Die Anzahl der ganzen Werte ist ja bekannt.
Ich habe jetzt also eine double Variable mit allen Zeitstempeln drin.
Um den Code von oben anzuwenden muss ich aus diesen ganzen Werten ja ein Array erstellen.

			String Zeile = null;
			double[] Maxwert = new double[3];
			double[] Minwert = { 1, 1, 1 };
			double Wert;
			// Spaltennamen ignorieren
			leser.leseZeile();
			while ((Zeile = leser.leseZeile()) != null) 
			{
				String[] Wertefeld = Zeile.split(";");```

Durch diesen Code wird die CSV eingelesen. Wir haben eine eigene Klasse für das importieren.

Wertefeld ist die Gesamte CSV und die Zahl ist die Spalte mit den jeweiligen Werten. Minwert und Maxwert gehört zu einem anderen Aufgabenteil

ich habe gestern

[QUOTE=SlaterB]doch wieder ein Schritt zurück und wie schon gewarnt: bevor du überhaupt an komplizierte Dinge denken kannst muss CSV aus dem Blickfeld verschwinden,

lies 5 Zeilen in Datenstrukturen ein und baue an einer zweiten Codestelle eine Ausgabe (System.out.println(), mit Schleife), Ergebnisausgabe in etwa

Anzahl Einträge: 5
1. Eintrag: a, b, c,
2. Eintrag: e, f, g
usw.

musst du jetzt nicht sklavisch nachbauen und hier abliefern, aber solltest du für dich in etwa können,
soweit Verständnis vorhanden? vorher alles andere unmöglich
[/QUOTE]

geschrieben,

wieso überlegst du zu Sekunden, wenn du noch nichtmal alle Zeitwerte aus dem Leser in ein Array überführt hast?..
das ist ganz klar eine vorherige Aufgabe

aus String[] Wertefeld wie bekannt den double holen und in ein Array schreiben,
den Index dazu nebenher in einer Variablen hochzählen, oder for-Schleife statt while

wenn Anzahl Einträge nicht bekannt, dann List statt Array, dazu schlau machen


Variablen unbedingt klein schreiben

schreibe Code in [JAVA ]-Tags, zitiere testweise Posting von jemand anderen um zu sehen wie einzutippen,
einen Button dafür gibt es im kleinen Editor anscheinend nicht