Räkna ut medelvärde av liknande objekt i treemap

Permalänk
Medlem

Räkna ut medelvärde av liknande objekt i treemap

Jag försöker lista ut hur jag ska få ut ett medelvärde ur min values(objekt) i en treemap och presentera resultatet i en string array.

Weatherdata objektet har dessa egenskaper

public class WeatherData { LocalDate date; String time; String temp; String quality;

Det ser ut såhär i treemapen. Key är Datum + klockslag som string. Value är objektet (datum,klockslag,temp,kvalitet)
(Map<String,WeatherData>)

--------Key------- ----------Value------------- 1946-01-01 07:00:00 : 1946-01-01, 07:00:00, -1.8, G 1946-01-01 13:00:00 : 1946-01-01, 13:00:00, -1.0, G 1946-01-01 18:00:00 : 1946-01-01, 18:00:00, -1.9, G 1946-01-02 07:00:00 : 1946-01-02, 07:00:00, -1.7, G 1946-01-02 13:00:00 : 1946-01-02, 13:00:00, -0.2, G 1946-01-02 18:00:00 : 1946-01-02, 18:00:00, -1.3, G 1946-01-03 07:00:00 : 1946-01-03, 07:00:00, -1.0, G 1946-01-03 13:00:00 : 1946-01-03, 13:00:00, -0.1, G 1946-01-03 18:00:00 : 1946-01-03, 18:00:00, -1.2, G

I string arrayen så ska man endast se medeltemperaturen för varje datum, alltså ska den presenteras såhär:

1946-01-01: -1.56 1946-01-02: -1.06 1946-01-03: -0.76

Det jag försöker göra är att plocka ut alla values till en objekt array(objektList), men om objektet redan finns i arrayen vill jag enbart addera objektets temp till objektet som finns i arrayen. Jag vet att jag inte får ut medelvärde just nu, vill bara se om dom lyckas summeras ihop, får lista ut hur jag gör med medelvärde senare.

for (Map.Entry<String,WeatherData> entry : subMap.entrySet()) { WeatherData value = entry.getValue(); if(!objektList.contains(value.date)){ objektList.add(value); }else{ for(int i = 0;i<objektList.size();i++){ if(objektList.get(i).date.equals(value.date)){ objektList.get(i).temp += value.temp; } } } }

Sedan för jag över det som finns i objekt arrayen till en string arrayen för att få ut rätt utskrift

//Till string lista for(int i = 0; i < objektList.size();i++){ stringList.add(objektList.get(i).date.toString() +": " + objektList.get(i).temp); }

Men det ser ut såhär vid utskrift, alltså är det något jag missar när jag försöker överföra till objekt arrayen.

1946-01-01: -1.8 1946-01-01: -1.0 1946-01-01: -1.9 1946-01-02: -1.7 1946-01-02: -0.2 1946-01-02: -1.3 ...osv

Någon som kan få mig att förstå vad jag missar ? Är det kanske onödigt att överföra till en objekt array? Går det att genomföra beräkningarna redan i treemap på något sätt?

Permalänk
Medlem

Du kan inte direkt beräkna, utan du måste göra subqueries.

Du kan t.ex först pmocka ut en lista på alla kända datum som finns, sen loopa den och hämta alla värden för det datumet och räkna medel.

Jag gillar att göra om data först till "mitt" förmat, på så sätt kan man abstrahera allt och kunna använda samma kod på många datakällor, bara cenom att byta konverteraren

Permalänk
Medlem
Skrivet av Wequ:

Jag försöker lista ut hur jag ska få ut ett medelvärde ur min values(objekt) i en treemap och presentera resultatet i en string array.

Weatherdata objektet har dessa egenskaper

public class WeatherData { LocalDate date; String time; String temp; String quality;

Det ser ut såhär i treemapen. Key är Datum + klockslag som string. Value är objektet (datum,klockslag,temp,kvalitet)
(Map<String,WeatherData>)

--------Key------- ----------Value------------- 1946-01-01 07:00:00 : 1946-01-01, 07:00:00, -1.8, G 1946-01-01 13:00:00 : 1946-01-01, 13:00:00, -1.0, G 1946-01-01 18:00:00 : 1946-01-01, 18:00:00, -1.9, G 1946-01-02 07:00:00 : 1946-01-02, 07:00:00, -1.7, G 1946-01-02 13:00:00 : 1946-01-02, 13:00:00, -0.2, G 1946-01-02 18:00:00 : 1946-01-02, 18:00:00, -1.3, G 1946-01-03 07:00:00 : 1946-01-03, 07:00:00, -1.0, G 1946-01-03 13:00:00 : 1946-01-03, 13:00:00, -0.1, G 1946-01-03 18:00:00 : 1946-01-03, 18:00:00, -1.2, G

I string arrayen så ska man endast se medeltemperaturen för varje datum, alltså ska den presenteras såhär:

1946-01-01: -1.56 1946-01-02: -1.06 1946-01-03: -0.76

Det jag försöker göra är att plocka ut alla values till en objekt array(objektList), men om objektet redan finns i arrayen vill jag enbart addera objektets temp till objektet som finns i arrayen. Jag vet att jag inte får ut medelvärde just nu, vill bara se om dom lyckas summeras ihop, får lista ut hur jag gör med medelvärde senare.

for (Map.Entry<String,WeatherData> entry : subMap.entrySet()) { WeatherData value = entry.getValue(); if(!objektList.contains(value.date)){ objektList.add(value); }else{ for(int i = 0;i<objektList.size();i++){ if(objektList.get(i).date.equals(value.date)){ objektList.get(i).temp += value.temp; } } } }

Sedan för jag över det som finns i objekt arrayen till en string arrayen för att få ut rätt utskrift

//Till string lista for(int i = 0; i < objektList.size();i++){ stringList.add(objektList.get(i).date.toString() +": " + objektList.get(i).temp); }

Men det ser ut såhär vid utskrift, alltså är det något jag missar när jag försöker överföra till objekt arrayen.

1946-01-01: -1.8 1946-01-01: -1.0 1946-01-01: -1.9 1946-01-02: -1.7 1946-01-02: -0.2 1946-01-02: -1.3 ...osv

Någon som kan få mig att förstå vad jag missar ? Är det kanske onödigt att överföra till en objekt array? Går det att genomföra beräkningarna redan i treemap på något sätt?

Om jag förstår dig rätt behöver du inte nycklarna från den ursprungliga TreeMap:en, utan kan jobba helt utifrån den LocalDate som sitter på varje värde? Om så är fallet kanske något sånt här kan fungera

TreeMap<String, Double> output = input.entrySet() .stream() .collect(Collectors.toMap( entry -> entry.getValue().date.toString(), entry -> Double.parseDouble(entry.getValue().temp), (tempSum, temp) -> tempSum + temp, () -> new TreeMap<>() ));

Detta ger dig en ny TreeMap<String, Double> där nyckeln är datumet utan klockslag och värdet är summan av alla ursprungsvärden på det datumet.

edit:
Du behöver så klart ha en lista på alla temperaturer för att kunna ta fram ett medelvärde. Här är en uppdaterad variant

TreeMap<String, List<Double>> output = input.entrySet() .stream() .collect(Collectors.toMap( entry -> entry.getValue().date.toString(), entry -> List.of(Double.parseDouble(entry.getValue().temp)), (temps, temp) -> Stream.of(temps, temp).flatMap(List::stream).collect(Collectors.toList()), () -> new TreeMap<>() ));

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

Du behöver så klart ha en lista på alla temperaturer för att kunna ta fram ett medelvärde. Här är en uppdaterad variant

TreeMap<String, List<Double>> output = input.entrySet() .stream() .collect(Collectors.toMap( entry -> entry.getValue().date.toString(), entry -> List.of(Double.parseDouble(entry.getValue().temp)), (temps, temp) -> Stream.of(temps, temp).flatMap(List::stream).collect(Collectors.toList()), () -> new TreeMap<>() ));

Jag försöker skriva av den för att förstå vad varje metod gör , men när jag kommer till "entry" blir det rödmarkerat och meddelandet "Cannot resolve symbol 'entry'".

Har du lust och förklara vad kodsnutten gör? Vad är entry för något?

Är inte direkt van vid sån där kod, mest använt for loopar etc.

Permalänk
Medlem
Skrivet av Wequ:

Jag försöker skriva av den för att förstå vad varje metod gör , men när jag kommer till "entry" blir det rödmarkerat och meddelandet "Cannot resolve symbol 'entry'".

Har du lust och förklara vad kodsnutten gör? Vad är entry för något?

Är inte direkt van vid sån där kod, mest använt for loopar etc.

Syntaxen entry -> entry.getValue().date.toString() är en anonym funktion som motsvarar

String getDateAsString(Map.Entry<String, WeatherData> entry) { return entry.getValue().date.toString(); }

Typen för entry kommer sig av .entrySet()-typen, dvs Set<Map.Entry<String, WeatherData>>.
Att det inte fungerar hos dig kan bero på att du kör Java i en version tidigare än 8. Från och med Java 8 finns det stöd för just dessa så kallade lambda-uttryck, även kända som anonyma funktioner.

Här är en kommenterad version

TreeMap<String, List<Double>> output = input.entrySet() .stream() .collect( Collectors.toMap( entry -> entry.getValue().date.toString(), // *1: tar fram ett nytt nyckelvärde entry -> List.of(Double.parseDouble(entry.getValue().temp)), // *2: varje entry omvandlas till en lista av temperaturer (temps, temp) -> Stream.of(temps, temp).flatMap(List::stream).collect(Collectors.toList()), // den här raden slår samman listor av temperaturer. Dvs [1.4] + [-0.3] = [1.4, -0.3] () -> new TreeMap<>() // säger att vi vill spara resultatet i en TreeMap. Att nyckelvärdet blir en String och varje värde är en List<Double> kommer sig av *1 och *2. ) );

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

Syntaxen entry -> entry.getValue().date.toString() är en anonym funktion som motsvarar

String getDateAsString(Map.Entry<String, WeatherData> entry) { return entry.getValue().date.toString(); }

Typen för entry kommer sig av .entrySet()-typen, dvs Set<Map.Entry<String, WeatherData>>.
Att det inte fungerar hos dig kan bero på att du kör Java i en version tidigare än 8. Från och med Java 8 finns det stöd för just dessa så kallade lambda-uttryck, även kända som anonyma funktioner.

Här är en kommenterad version

TreeMap<String, List<Double>> output = input.entrySet() .stream() .collect( Collectors.toMap( entry -> entry.getValue().date.toString(), // *1: tar fram ett nytt nyckelvärde entry -> List.of(Double.parseDouble(entry.getValue().temp)), // *2: varje entry omvandlas till en lista av temperaturer (temps, temp) -> Stream.of(temps, temp).flatMap(List::stream).collect(Collectors.toList()), // den här raden slår samman listor av temperaturer. Dvs [1.4] + [-0.3] = [1.4, -0.3] () -> new TreeMap<>() // säger att vi vill spara resultatet i en TreeMap. Att nyckelvärdet blir en String och varje värde är en List<Double> kommer sig av *1 och *2. ) );

Oj ja det gjorde saken lite klarare!

Om man ska applicera det som händer i for-loop tänk, sker alla steg i en loop eller är det flera nästlade loopar?

Permalänk
Medlem
Skrivet av Wequ:

Oj ja det gjorde saken lite klarare!

Om man ska applicera det som händer i for-loop tänk, sker alla steg i en loop eller är det flera nästlade loopar?

Gissningsvis bara en.

Visa signatur

Kom-pa-TI-bilitet