Statistische Auswertung Pakete

Dann muss ich mich jetzt wohl entscheiden, ob ich mir noch die notwendigen SQL-Kenntnisse, die mit Sicherheit nicht schaden würden, aneigene oder ob es für diese Problemstellung nicht einfacher und zielgerichteter ist, das ganze mit Java zu lösen.
@CyborgBeta
Vielen Dank schonmal, sieht auf jeden Fall viel viel kürzer und eleganter aus, als ich gedacht hatte.

Viel schwieriger als man denkt, nicht einfach mal so geschrieben, echte aufgabe; Durchschnitt über alle Werte:

[SPOILER]```import java.io.;
import java.text.
;
import java.util.*;

/**

  • @author CB
    */
    public class Temp {

    private static HWLVPaket[] pakete = new HWLVPaket[8];

    static {
    for (int i = 0; i < pakete.length; i++) {
    final int fi = i;
    pakete** = new HWLVPaket(fi / 2) {
    @Override
    public boolean valid() { // prüfe außerdem Uhrzeit
    return get() >= fi % 2;
    }
    };
    }
    }

    public static void main(String[] args) throws IOException {
    int i = 0;
    BufferedReader br = new BufferedReader(new FileReader(“D:\Downloads\20150820_EM06.txt”));
    String line = br.readLine();
    while ((line = br.readLine()) != null) {
    String[] split = line.split(";");
    if (split.length == 11) {
    for (HWLVPaket p : pakete) {
    p.add(split);
    }
    } else {
    System.out.println(Arrays.toString(split)); // komische Zeile
    }
    //i++;
    if (i == 10) {
    break;
    }
    }
    br.close();

     for (HWLVPaket p : pakete) {
         System.out.println(p.getAvr());
     }
    

    }
    }

abstract class HWLVPaket {

private static final SimpleDateFormat sdf = (SimpleDateFormat) DateFormat.getDateTimeInstance(); // parse Uhrzeit

int index; // übergib außerdem Uhrzeit
int h, w, l, v;

int anz = 0;
int sum = 0;
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;

public HWLVPaket(int index) {
    this.index = index;
}

public void add(String[] s) {
    parse(s);
    if (valid()) {
        int i = get();
        anz++;
        sum += i;
        min = i < min ? i : min;
        max = i > max ? i : max;
    }
}

public double getAvr() {
    return sum / (double) anz;
}

public void parse(String[] s) {
    h = Integer.parseInt(s[7]);
    w = Integer.parseInt(s[8]);
    l = Integer.parseInt(s[9]);
    v = Integer.parseInt(s[10]);
}

public int get() {
    switch (index) {
        case 0:
            return h;
        case 1:
            return w;
        case 2:
            return l;
        case 3:
            return v;
        default:
            throw new AssertionError();
    }
}

public abstract boolean valid();

}```[/SPOILER]

144.26474241870662
144.26474241870662 => Höhe gibt es immer
266.47219583485565
266.56959064327486 => Weite gibt es fast immer
388.813920350749
388.84233411283253 => Länge gibt es fast immer
22266.31356427684
22296.459328917997 => Volumen gibt es oft nicht

Wegen der Uhrzeit würde ich das einfach sortieren, aber es gibt jeweils 2x Uhrzeit.

@Dathor : Bitte nicht jedesmal nennen/quoten, leuchtet alles auf hier.

in der Tat besser nicht zu oft Bezug und Code besser nicht zu ernst nehmen

hier kompliziert doppelte Auswertung mit abstrakter Methode mit modulo auf Index allein für >0-Prüfung…

die Werte jeder Zeile werden nebenher 8fach (!) geparst, und in den 8 Unterobjekten je nach Index nur einer davon genutzt

so ungern ich auch direkt Bezug nehme, wie oft es auch durch CyborgBeta auf Korrektur seiner komischen Codes hinausläuft, Sperrung in ständiger Schwebe,
hier als Warnung vor schlimmeren Folgen eine (ungetestete) zweite Variante dieses Ansatzes

[spoiler]

import java.text.*;
import java.util.*;

/**
 * @author 
 */
public class Test2 {
    
    private static HWLVPaket[] pakete = new HWLVPaket[4];

    static  {
        for (int i = 0; i < pakete.length; i++) {
            pakete** = new HWLVPaket();
        }
    }

    public static void main(String[] args) throws IOException  {
        int i = 0;
        BufferedReader br = new BufferedReader(new FileReader("D:\\Downloads\\20150820_EM06.txt"));
        String line = br.readLine();
        while ((line = br.readLine()) != null) {
            String[] split = line.split(";");
            if (split.length == 11) {
                int h = Integer.parseInt(split[7]);
                int w = Integer.parseInt(split[8]);
                int l = Integer.parseInt(split[9]);
                int v = Integer.parseInt(split[10]);

                pakete[0].add(h);
                pakete[1].add(w);
                pakete[2].add(l);
                pakete[3].add(v);
            }  else  {
                System.out.println(Arrays.toString(split)); // komische Zeile
            }
            // i++;
            if (i == 10)  {
                break;
            }
        }
        br.close();

        for (HWLVPaket p : pakete)   {
            System.out.println(p.getAvrNotZero() + " - " + p.getAvrAll());
        }
    }
}

class HWLVPaket {

    private static final SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateTimeInstance(); // parse Uhrzeit

    // übergib außerdem Uhrzeit

    int anzAll = 0;
    int anzNotZero = 0;
    int sum = 0;
    int min = Integer.MAX_VALUE;
    int max = Integer.MIN_VALUE;

    public HWLVPaket() {

    }

    public void add(int value) {
        int v = value;
        anzAll++;
        if (v > 0)  {
            anzNotZero++;
            sum += v;
            min = v < min ? v : min; // min 0 nicht dabei
            max = v > max ? v : max;
        }
    }

    public double getAvrAll() {
        return sum / (double)anzAll;
    }

    public double getAvrNotZero() {
        return sum / (double)anzNotZero;
    }
}
```[/spoiler]

Mit einer abstrakt übergebenen Condition war es noch viel schlimmer.

An welcher Stelle im Code sollte man gruppieren, Slater?

Heute ist echt nicht mein Tag.

auch wenn dieses Thema nicht so schlimm wie andere ist, mehr allgemein als hier gesprochen:

  • du sollst nie in Themen von anderen User Fragen zu deinen Code stellen, wenn dieser Punkt erreicht, dann ist die Frage die falsche Reaktion darauf,
    lasse doch einfach meine Variante dazu unkommentiert oder sage evtl. schlicht dass du es anders siehst und fertig

  • und wann ist je dein Tag? verschone doch andere von deinen nicht-Tagen,
    auf jeden Fall verzichtet immer auf solche Twitter-Meldungen über deinen Status, themenfremd

Aber hier muss ich einmal differenzieren, ich hatte eigentlich eine Fragen zum Inhalt und Aufbau der gegebenen CSV-Datei (und ob diese Konstruiert ist).

macht keinen Unterschied, die Frage war an mich gerichtet und praktisch keine Frage kann es so geben,
ein Fachthema ist nicht deine Spielwiese für Statistiken, Performance-Wettbewerbe, Was wäre Wenn-Fragen,
Codeverbesserungen deiner Variante (außer notgedrungen zur Warnung der Allgemeinheit),
du brauchst nicht beim Themenstarter nachfragen wann er sich endlich wieder meldet und und und,

freilich kann all das mal vorkommen, von 100 Themen vielleicht in 5, dann oft noch im Einverständnis mit Themenstarter,
oder nach Tagen bei geklärten Thema,
bei dir in 95 von 100 auf deine Initiative hin mittendrin Themaübernahme ohne Rücksicht auf alle anderen…

einfach alles in Ruhe lassen, nur Fragen beantworten wenn sie kommen, eigene Codelösungen eher vermeiden,
besonders komplett neue gegenüber Ergänzung vorhandener

Ein Punkt der hier noch nicht so erwähnt wurde sind die Erweiterungen die in Java 8 hinzugekommen sind.

Insbesondere die Stream-API in Kombination mit Lambdas bringen hier vieles mit, das einen so Standard-Aufgaben recht einfach, gut und schnell bewältigen lässt.

Zum Beispiel kann ein IntStream mit einem IntSummaryStatistics-Collector ein IntSummaryStatistics-Objekt zurückliefern, das einem Minimum, Maximum, Summe, Durchschnitt usw. ootB liefert.


stats.getCount();
stats.getSum();
stats.getMin();
stats.getMax();
stats.getAverage();```


Es gibt Gruppier, Filter und Mapping-Funktionen die einem vieles abnehmen und für verständlichen Code (bischen Übung gehört dazu) liefern.


Ein Vorteil den ich dabei sehe ist, dass hier weder eine Datenbank noch SQL-Kenntnisse gebraucht werden. Java 8 Installation ist ausreichend.

Dateien können auch als Stream verarbeitet werden. Siehe [Files (Java Platform SE 8 )](http://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#lines-java.nio.file.Path-java.nio.charset.Charset-)
Finde ich eine gute Weiterentwicklung, Alternative zur Arbeit mit dem BufferedReader.

Zum Testen, Entwicklen kann es bei Streams noch hilfreich sein, die Anzahl der Elemente zu beschränken, z.B. via [Stream (Java Platform SE 8 )](http://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#limit-long-)

Je nachdem wie lange so ein Durchlauf benötigt, gibt es damit viel schneller Feedback.

Als Datenklasse kannst du nehmen (und dann nach Stunden und vorher nach Tagen sortieren, hält aber alles im Speicher, was bei 2 MB nicht schlimm) [wenn man die neuen Features von Java 8 (noch) nicht verwenden will]:

[SPOILER]```class DHWLVPaket {

private static final SimpleDateFormat sdf = (SimpleDateFormat) DateFormat.getDateTimeInstance();

static {
    sdf.applyPattern("yyyy-M-d H:m:s");
}

Date d;
int kat;
int h, w, l, v;

public DHWLVPaket(String[] s) throws ParseException {
    Date d1 = sdf.parse(s[1]), d2 = sdf.parse(s[2]);
    d = new Date((d2.getTime() - d1.getTime()) / 2 + d1.getTime());
    kat = (int) (((d.getTime() + 7200000) / 3600000) % 24);
    h = Integer.parseInt(s[7]);
    w = Integer.parseInt(s[8]);
    l = Integer.parseInt(s[9]);
    v = Integer.parseInt(s[10]);

    System.out.println(toString());
}

@Override
public String toString() {
    return "DHWLVPaket{" + "d=" + d + ", kat=" + kat + ", h=" + h + ", w=" + w + ", l=" + l + ", v=" + v + '}';
}

}```[/SPOILER]
Somit hab ich raus:

[SPOILER]

0 Uhr
111.74803149606299
260.2035433070866
379.11811023622045
18095.403903015966

1 Uhr
136.1308807923594
264.1960368011323
376.6802263883976
20437.97660404112

2 Uhr
159.16602140742427
276.28991118196313
410.07652015486224
26159.356492027335

3 Uhr
151.6969696969697
277.15371102327623
402.12626262626264
25097.76087912088

4 Uhr
160.00595238095238
273.7886904761905
394.45089285714283
23593.135416666668

5 Uhr
144.78787878787878
263.39076576576576
383.2980877390326
21152.833333333332

6 Uhr
120.82432432432432
243.17006802721087
367.06756756756755
18140.993103448276

7 Uhr
NaN
NaN
NaN
NaN

8 Uhr
NaN
NaN
NaN
NaN

9 Uhr
NaN
NaN
NaN
NaN

10 Uhr
NaN
NaN
NaN
NaN

11 Uhr
NaN
NaN
NaN
NaN

12 Uhr
NaN
NaN
NaN
NaN

13 Uhr
NaN
NaN
NaN
NaN

14 Uhr
149.92857142857142
271.73214285714283
469.9107142857143
27040.035714285714

15 Uhr
182.37717601547388
261.8422071636012
380.0203094777563
24966.895247332686

16 Uhr
189.850144092219
304.44956772334297
440.0086455331412
34499.109510086455

17 Uhr
42.92307692307692
135.92307692307693
201.15384615384616
1204.0

18 Uhr
135.43381535038932
232.59065628476085
341.9182424916574
16155.59677419355

19 Uhr
NaN
NaN
NaN
NaN

20 Uhr
157.5609195402299
272.241855116903
388.11724137931037
23065.79631053036

21 Uhr
153.27506621263714
268.6787878787879
400.8959515701854
23550.73568448995

22 Uhr
125.875
229.35416666666666
369.3333333333333
18253.541666666668

23 Uhr
87.45736434108527
209.35271317829458
307.59302325581393
8902.744186046511

Gerundet:

0 Uhr
111.75
260.2
379.12
18095.4

1 Uhr
136.13
264.2
376.68
20437.98

2 Uhr
159.17
276.29
410.08
26159.36

3 Uhr
151.7
277.15
402.13
25097.76

4 Uhr
160.01
273.79
394.45
23593.14

5 Uhr
144.79
263.39
383.3
21152.83

6 Uhr
120.82
243.17
367.07
18140.99

7 Uhr
0.0
0.0
0.0
0.0

8 Uhr
0.0
0.0
0.0
0.0

9 Uhr
0.0
0.0
0.0
0.0

10 Uhr
0.0
0.0
0.0
0.0

11 Uhr
0.0
0.0
0.0
0.0

12 Uhr
0.0
0.0
0.0
0.0

13 Uhr
0.0
0.0
0.0
0.0

14 Uhr
149.93
271.73
469.91
27040.04

15 Uhr
182.38
261.84
380.02
24966.9

16 Uhr
189.85
304.45
440.01
34499.11

17 Uhr
42.92
135.92
201.15
1204.0

18 Uhr
135.43
232.59
341.92
16155.6

19 Uhr
0.0
0.0
0.0
0.0

20 Uhr
157.56
272.24
388.12
23065.8

21 Uhr
153.28
268.68
400.9
23550.74

22 Uhr
125.88
229.35
369.33
18253.54

23 Uhr
87.46
209.35
307.59
8902.74

[/SPOILER]
Alles andere jetzt zu posten, wäre eine Komplettlösung/‘Businesslösung’. Hast du Fragen dazu?

        kat = (int) (((d.getTime() + 7200000) / 3600000) % 24);

die +7200000 (ohne Erklärung wie alles) scheinen nur da zu sein, um den Unterschied zwischen der Millizeit (~GMT) und der aktuellen Uhrzeit in Deutschland zu überbrücken,
im Sommer bei aktiver Sommerzeit wäre die berechnete Stunde durchgehend eine andere als aktuell im Winter…,

an Zeitumstellung lieber nicht zu denken, wobei das freilich immer eine Schwierigkeit darstellt,
Calendar bietet sich an

soviel als neue nötige Warnung, und wenn hoffentlich nicht Dathor weitere Versionen ermutigt,
dann ist das nun die letzte erlaubte, jede weitere wird gelöscht

@ionutbaiu
Danke für den Tipp. Ich kenne mich mit Streams nur leider auch noch nicht aus und denke, dass gerade dafür, in den Java Basics besser zu werden, die wenn auch unelegante “Kopf durch die Wand” Methode im Moment mehr bringt. Wenn ich damit erfolgreich war oder scheitere, kann ich ja immer noch versuchen auf deine elegante Version umzusteigen.
In erster Linie muss es im Moment nur funktionieren.


Bin gerade dabei meinen Code so umzuschreiben, so dass ich pro Zeile ein Paketobjekt erstelle. Ich denke, dass ist sinnvoll, weil es noch andere Spalten gibt, die ich hier in der CSV der Einfachheit halber weggelassen habe (z.B. Barcodes), die aber auch gezählt und ausgewertet werden müssen.

Ich würde dann jetzt alle Paketobjekte zunächst in eine allgemeine (noch unsortierte) ArrayList packen.

Wie würde dann eine Methode aussehen, die das gleiche liefert, wie die “add-Methode” von @CyborgBeta bzw. wo würde ich die Methode aufrufen, um unnötige doppelte Durchgänge der kompletten List zu vermeiden?
Würde ich die Methode für meine Objekt Klasse “DHWLVPaket” schreiben? Oder einfach eine Methode für meine Hauptklasse wo auch die Main Methode steht?

Zwei Uhrzeiten, zwischen ein paar Minuten oder Stündchen, Mitte kann gewählt werden.

Vielleicht nachts keine Bestellung möglich, vom System.

Stimmt, das ist ja noch vor der Umstellung, wir sind GMT+2 oder GMT+1.

1000 * 60 * 60 (* 24) * 2 ==> ziehe 2 Stunden ab

Jedenfalls, sortieren möglich, nach “Kategorie”.

Last but not least: Ich hab deine Kritik verstanden, Slater.

wenn nicht paar Mal durchlaufen dann braucht es strenggenommen keine Liste,

man kann zwar wie gesehen Min/ Max/ Summe in einem Durchlauf berechnen,
getrennt mehrfach einzeln wäre aber auch nicht allzu kritisch,
besonders nicht am Anfang, später immer noch zu ändern wenn gewünscht


wo welche Methode steht, darauf kommt es erstmal nicht so sehr an,
Einlesen ist eine Methode, schreibt alles in eine Haupt-Liste,

eine zweite Methode könnte die Haupt-Liste durchlaufen und die Pakete in Teillisten (je Modul, Stunde usw., dafür ja auch zu rechnen) verteilen,
in etwa wie in Posting #11 schon angesprochen, oder gleich damit etwas berechnen, das add() aufrufen, ohne Teilliste

weder eine Klasse, die ein einzelnes Paket = CSV-Zeile darstellt, noch eine die Min/ Max/ Summe komplett verwaltet, ist dafür geeignet,
um direkt die Frage zu beantworten, das sollte allgemeiner passieren

falls man eine Teilliste fertig zusammengestellt, kann eine MinMaxSumme-Klasse die freilich übergeben bekommen und intern durchlaufen

das add() wie schon zu sehen ist nicht viel anders zu machen,


wichtiger großer Mittelteil und noch nur wenig behandelt dürfte im Moment sein, von einem Paket aus die Teilstatistik nach Modul & Co. zu bestimmen, dort hinzufügen,
überhaupt auch eine Struktur aller Teilstatistiken,

womöglich schon bald ein Ansatz dazu von anderen hier zu zu lesen, ob das gut oder schlecht ist sei mal dahingestellt,
versuche es solange vielleicht etwas alleine, trenne doch für einfachen Anfang lediglich nach Modul auf

[QUOTE=Dathor]Wie würde dann eine Methode aussehen, die das gleiche liefert, wie die “add-Methode” von @CyborgBeta bzw. wo würde ich die Methode aufrufen, um unnötige doppelte Durchgänge der kompletten List zu vermeiden?
Würde ich die Methode für meine Objekt Klasse “DHWLVPaket” schreiben? Oder einfach eine Methode für meine Hauptklasse wo auch die Main Methode steht?[/QUOTE]

Die add-Methode könnte so bleiben, müsste aber in einer eigenen Stats-Klasse für Höhe, Weite, Länge, Volumen stehen. Du brauchst nur einmal über die Liste laufen und kannst die Stats-Klasse(n) jeweils resetten / zurücksetzen. Es wäre aber auch möglich, die Liste aufzuteilen.

@CyborgBeta
Hatte dir mal ne PM geschriebe zu Frage zu deinem Code, weil die hier vermutlich nicht für jeden interessant ist.

@Dathor ,

[QUOTE=Dathor]@CyborgBeta
Hatte dir mal ne PM geschriebe zu Frage zu deinem Code, weil die hier vermutlich nicht für jeden interessant ist.[/QUOTE]

und ich hab sie beantwortet, aber bitte nicht immer mit @ nennen, ich/jeder weiß doch, wen du meitest.