Plant Discovery от Final Exam
Моля за малко помощ, докарвам логиката но в принтирането се спъвам .
Ако някой има решение на 100/100 моля да сподели .
Ето го и кода ми:
https://pastebin.com/iQqrBpRv
Благодаря предварително
Моля за малко помощ, докарвам логиката но в принтирането се спъвам .
Ако някой има решение на 100/100 моля да сподели .
Ето го и кода ми:
https://pastebin.com/iQqrBpRv
Благодаря предварително
Имаше няколко пропуска по условието, като например да се извежда "error" при невалидна команда, както и да се презаписва rarity, ако растението бъде въведено повече от веднъж в началото.
Тази задача би се решила доста по-лесно и прегледно с помощен клас, но ето и оправеното решение с два Map-а :
import java.util.*;
public class PlantDiscovery {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Map<String, Integer> plants = new HashMap<>();
Map<String, List<Double>> rating = new HashMap<>();
int n = Integer.parseInt(scanner.nextLine());
for (int i = 0; i < n; i++) {
String[] input = scanner.nextLine().split("<->");
String plant = input[0];
int rarity = Integer.parseInt(input[1]);
plants.compute(plant, (k, v) -> rarity);
rating.putIfAbsent(plant, new ArrayList<>());
}
String input;
while (!"Exhibition".equals(input = scanner.nextLine())) {
String[] tokens = input.split(": ");
String command = tokens[0];
String[] elements = tokens[1].split(" - ");
String name = elements[0];
if (!plants.containsKey(name)) {
System.out.println("error");
continue;
}
switch (command) {
case "Rate":
double rate = Double.parseDouble(elements[1]);
rating.get(name).add(rate);
break;
case "Update":
int rarity = Integer.parseInt(elements[1]);
plants.compute(name, (k, v) -> rarity);
break;
case "Reset":
rating.get(name).clear();
break;
default:
System.out.println("error");
}
}
System.out.println("Plants for the exhibition:");
plants.entrySet()
.stream()
.sorted(Map.Entry.<String, Integer>comparingByValue()
.thenComparingDouble(x -> rating.get(x.getKey()).stream()
.mapToDouble(Double::doubleValue)
.average().orElse(0.0))
.reversed())
.forEach(e -> System.out.printf("- %s; Rarity: %d; Rating: %.2f%n", e.getKey(), e.getValue(),
rating.get(e.getKey()).stream().mapToDouble(Double::doubleValue).average().orElse(0.0)));
}
}
Благодаря ти много , да знаех че нямах случая за "error", но ме чупеше принтирането и сортирането едновременно на двата мапа,понеже никъде не го бяха показвали и не успях да намеря инфо в интернет.Интересно,досега не бях използвал "compute".Би ли ми обяснил накратко в кои случаи е удобно да се използва.:)
@SimeonKazandzhiev
Извинявам се за закъснелия отговор.
Map#compute(K, BiFunction(K, V)) ни дава възможност едновременно да достъпим и да променим стойността на вече съществуващ ключ. Това е полезно, например, ако искаме да конкатенираме стрингове, както е показано и в документацията:
Друго приложение е, ако искаме да сумираме старата стойност с нова. Например, ако в конкретната задача се искаше при повторно въвеждане на растение новото rarity да се добави към вече съществуващото:
Забележете, че задължително трябва да се прави проверка за null на старата стойност, преди тя да бъде използвана (ще е null ако растението се въвежда за първи път или ако по някаква причина е имало стойност null). Може да се използва тернарен оператор (примера от официалната документация) или Objects#requireNonNullElse(T obj, T defaultObj) - и двете правят едно и също в случая.
След като изяснихме това, вече сигурно се досещате, че използването на compute в конкретната задача е абсолютно ненужно (и нежелателно) и може да се заменени с Map#put(K key, V value), което ни дава желаната функционалност, без да събужда въпроси какво прави и защо е използвано (т.е. допринася за четимостта на кода)
Здравей MartinBG,
Можеш ли да напишеш на части разбито по-подробно какво се први в тази част на сортирането без да се ползват готовите методи Map.Entry.<String, Integer>comparingByValue() .thenComparingDouble. Благодаря ти. Разбирам какво е сортирането спрямо уловието, но синтаксиса ми е доста сложен към момента и ако знаеш нещо по-лесно, много ще ми помогнеш :)
.sorted(Map.Entry.<String, Integer>comparingByValue() .thenComparingDouble(x -> rating.get(x.getKey()).stream() .mapToDouble(Double::doubleValue) .average().orElse(0.0)) .reversed())
@Georgieva_Nadezhda
Както писах и по-горе, решението с използване на 2 Map-а не е оптимално, защото кодът е по-труден за четене, поддръжка и модифициране (например, ако трябва да добавим нов параметър към всяко растение или пък да пазим списък с имената на хората, които вече са оценили растението).
Сложното сортиране (като запис и синтаксис) е следствие от горното, защото трябва да се използват и двата мапа:
Решението, при което се използва помощен клас Plant би решило тези проблеми и ще улесни сортировката, защото ще имаме само един Map<String, Plant> plants:
Добро утро, @MartinBG, много ти благодаря за насоките, чудех се как е най-добре да се подхожда към такива задачи, за които аз си мисля, че ми трябват 2 мапа, а то всъщност мап с клас е правилния подход. Почвам да пренаписвам няколко задачки сега. Благодаря за разясненията още веднъж. Хубав ден 🙃