Korrigierte <String> Liste zurückgeben

Hallo zusammen.

Es sollte eigentlich richtig simpel sein ... Zuerst eine Liste von Strings, Element für Element, überprüfen, ob da bestimmte chars vorkommen oder nicht. Und dann davon ausgehend einige El. löschen, andere verdoppeln und dritte einfach so belassen:
[CODE lang="java" title="List ..."]public static void main(String[] args) {
ArrayList<String> liste = new ArrayList<>();
liste.add("Rose");
liste.add("Lilly");
liste.add("Lora");
liste = correct(liste);

for (String s : liste) {
System.out.println(s);
}
}

public static ArrayList<String> correct(ArrayList<String> liste) {
for (int i = 0; i < liste.size(); i++) {
String p = liste.get(i);
// p.toLowerCase();
if (!p.contains("l") && p.contains("r")) {
liste.remove(i);
} else if (p.contains("l") && !p.contains("r")) {
liste.add(p);
}
}
return liste;
}[/CODE]

Es sollte folgender output kommen:

Lilly
Lilly
Lora

... kommt aber

Rose
Lilly
Lilly

... raus

Ich sehe den Fehler einfach nicht.

Sieht vielleicht jemand, was ich falsch mache?

VD im Voraus.
 
K

kneitzel

Gast
Gib doch einfach einmal ein paar Informationen mehr aus!

Paar generelle Probleme:
a) Du bist bei Element i, dieses Löschst Du. Danach wird i hoch gezählt (for-Schleife). Welches Element prüfst Du denn dann danach?
Also ite Element ist z.B. das Dritte. Das löschst Du. Damit verschieben sich alle Elemente und Du machst mit dem neuen vierten Element weiter....

b) Du fügst am Ende das Element noch einmal hinzu. Und dann kommst Du zu dem Element: Was passiert dann mit der Kopie? (Gut, dass durch a) es in diesem Fall kein Problem gibt :) )

c) Prüf einmal: "Lilly".contains("l"); und "Rose".contains("r") - da fällt dir bestimmt auch eine Problematik auf ...
 
Gib doch einfach einmal ein paar Informationen mehr aus!

Paar generelle Probleme:
a) Du bist bei Element i, dieses Löschst Du. Danach wird i hoch gezählt (for-Schleife). Welches Element prüfst Du denn dann danach?
Also ite Element ist z.B. das Dritte. Das löschst Du. Damit verschieben sich alle Elemente und Du machst mit dem neuen vierten Element weiter....

b) Du fügst am Ende das Element noch einmal hinzu. Und dann kommst Du zu dem Element: Was passiert dann mit der Kopie? (Gut, dass durch a) es in diesem Fall kein Problem gibt :) )

c) Prüf einmal: "Lilly".contains("l"); und "Rose".contains("r") - da fällt dir bestimmt auch eine Problematik auf ...
Wenn das Wort 'r'enthält, aber kein 'l', dann soll es gelöscht werden. Wenn 'l' und 'r' - soll es einfach so belassen werden. Und wenn 'l', aber kein 'r' - dann soll es verdoppelt werden.

Also, Rose sollte gelöscht werden, Lilly verdoppelt und Lora bleibt wo sie ist. Die toLowerCase() will auch irgendwie nicht richtig funktionieren. Ich komm da einfach nicht weiter 😞
 
K

kneitzel

Gast
Strings können nicht verändert werden. Die Methode gibt einen neuen String zurück. Daher wäre der Punkt mit einem:
Java:
p = p.toLowerCase();
zu lösen.

Bleiben aber die anderen Punkte, zu denen Du eine Lösung finden musst...

Edit: beschreibe doch ganz genau, wie du vorgehen würdest, wenn du es mit Stift und Papier machen würdest...
 
1) Zuesrt lösche ich Rose aus der Liste. -> Liste hat nur 2 Elemente dann.
2) Lilly soll verdoppelt werden, also die Plätze 1 und 0 haben.
3) Lora soll auf Platz 3 (index 2) verschoben werden.

Ich begreife wirklich nicht, wo mir der Fehler unterlaufen ist.
 
Strings können nicht verändert werden. Die Methode gibt einen neuen String zurück. Daher wäre der Punkt mit einem:
Java:
p = p.toLowerCase();
zu lösen.

Bleiben aber die anderen Punkte, zu denen Du eine Lösung finden musst...

Edit: beschreibe doch ganz genau, wie du vorgehen würdest, wenn du es mit Stift und Papier machen würdest...
Seltsamerweise klappt es rückwärts:

Java:
public static ArrayList<String> correct(ArrayList<String> liste) {
        for (int i = liste.size() - 1; i >= 0; i--) {
            String p = liste.get(i).toLowerCase();
            if (!p.contains("l") && p.contains("r")) {
                liste.remove(i);
            } else if (p.contains("l") && !p.contains("r")) {
                liste.add(i, p);
            }
        }
        return liste;
    }

🤣 Ich krieg eine Krise ...
 

Neumi5694

Top Contributor
Listen rückwärts abarbeiten ist immer einfacher, da sich beim Löschen oder Einfügen/Hinzufügen die noch abzuarbeitenden Indizes nicht verändern.
Wenn du aufsteigend arbeitest, musst du bei jedem Löschvorgang den Index reduzieren und bei jedem Insert-Vorgang den Index erhöhen.
 
K

kneitzel

Gast
Man kann auch:
A) bei den Indices sorgfältig vorgehen. Man muss halt nur gut genug aufpassen, wo man gerade ist und bis wohin man laufen muss. Ist nur etwas komplexer als das rückwärts durchgehen.
B) einfach eine neue Liste erstellen in der man Elemente einfügt. Dann müsste man einem am Ende die neue Liste zurückgeben oder die original Liste leer machen und dann alle Eleme te einfügen.

Generell sollte die Übung aber sein, Dinge wirklich genauer zu betrachten! Oberflächige Beschreibungen muss man runter brechen. Daran scheitert es doch schon. Eine Beschreibung wie in #5 ist nicht wirklich sinnvoll.
 
Man kann auch:
A) bei den Indices sorgfältig vorgehen. Man muss halt nur gut genug aufpassen, wo man gerade ist und bis wohin man laufen muss. Ist nur etwas komplexer als das rückwärts durchgehen.
B) einfach eine neue Liste erstellen in der man Elemente einfügt. Dann müsste man einem am Ende die neue Liste zurückgeben oder die original Liste leer machen und dann alle Eleme te einfügen.

Generell sollte die Übung aber sein, Dinge wirklich genauer zu betrachten! Oberflächige Beschreibungen muss man runter brechen. Daran scheitert es doch schon. Eine Beschreibung wie in #5 ist nicht wirklich sinnvoll.
Ich weiß. Eigenen Denkprozess zu strukturieren ist gar nicht so einfach, wie man denkt. Und wenn, wie Sie richtig gesagt haben, nicht mal mit Stift und Papier eine mögliche Lösung finden kann, da bringt es auch nicht viel, wenn man eine Datenstruktur nach der anderen einfach ausprobiert in der Hoffnung, dass es vielleicht klappt.

Man lernt aber trotz oder dank der Fehler immer etwas dazu.

Nochmals vielen Dank für Ihre Hilfe.
 

betatwo

Mitglied
Und dann davon ausgehend einige El. löschen, andere verdoppeln und dritte einfach so belassen
Ist relativ simple, erstelle eine neue ArrayList. Es gibt zwar keine Probleme beim löschen wenn du von hinten nach vorne durchläufst, aber je nachdem, wo neue Elemente eingefügt werden sollen, kann das zu Problemen führen. (infiniter Regress oder ConcurrentModificationException beim Iterator)

Java:
        for (int i = liste.size() - 1; i >= 0; i--) {
            String p = liste.get(i).toLowerCase();
            if (!p.contains("l") && p.contains("r")) {
                liste.remove(i);
            } else if (p.contains("l") && !p.contains("r")) {
                liste.add(i, p);
            }
        }
sollte allerdings funktionieren, aber komm nicht auf die Idee, Iterator zu verwenden oder vorne einzufügen.

Wie gesagt, am schönsten ist es, eine neue Liste zu erstellen...
 
Ist relativ simple, erstelle eine neue ArrayList. Es gibt zwar keine Probleme beim löschen wenn du von hinten nach vorne durchläufst, aber je nachdem, wo neue Elemente eingefügt werden sollen, kann das zu Problemen führen. (infiniter Regress oder ConcurrentModificationException beim Iterator)

Java:
        for (int i = liste.size() - 1; i >= 0; i--) {
            String p = liste.get(i).toLowerCase();
            if (!p.contains("l") && p.contains("r")) {
                liste.remove(i);
            } else if (p.contains("l") && !p.contains("r")) {
                liste.add(i, p);
            }
        }
sollte allerdings funktionieren, aber komm nicht auf die Idee, Iterator zu verwenden oder vorne einzufügen.

Wie gesagt, am schönsten ist es, eine neue Liste zu erstellen...
Die Lösung mit einer neuen Liste war auch als "Musterlösung" vorhanden (es geht um eien OnlineKurs), ich wollte aber rausfinden, wo und was mit meiner Variante nicht stimmt.

Danke für die Antwort.
 
K

kneitzel

Gast
Dann lass uns das doch einfach einmal im Detail erst einmal ausformulieren:
Wir starten beim ersten Element. (Aktuelle Stelle ist 0)
So lange ein Element an der aktuellen Stelle vorhanden ist:
- Wenn das Element an der aktuellen Stelle gelöscht werden soll, dann lösche das Element
- Sonst: Wenn das Element verdoppelt werden soll, dann füge das Element an der aktuellen Stelle noch einmal an. Gehe 2 Elemente weiter.
- Sonst: gehe ein Element weiter

Das kann man auch austesten mit Papier und Stift. Hier rate ich Dir, das wirklich zu üben. Am Anfang ist es schwer, aber mit der Zeit macht man sowas dann problemlos im Kopf. Und es hilft auch, sich das dann besser vorstellen zu können!

Bei sprachlichen Formulierungen muss man so lange verfeinern, bis man auf eine Ebene kommt, die 1:1 in das Programm übersetzt werden kann. Und das geht dann mit dem Text oben schon sehr gut. (Das mit dem lower case haben wir da nicht ... aber das ignorieren wir mal einfach ...)
Java:
    public static ArrayList<String> correct(ArrayList<String> liste) {
        int index = 0;
        while (index < liste.size()) {
            String currentElement = liste.get(index).toLowerCase();
            if (!currentElement.contains("l") && currentElement.contains("r")) {
                liste.remove(index);
            } else if (currentElement.contains("l") && !currentElement.contains("r")) {
                liste.add(index, liste.get(index));
                index = index + 2;
            } else {
                index++;
            }
        }
        return liste;
    }
 
Dann lass uns das doch einfach einmal im Detail erst einmal ausformulieren:
Wir starten beim ersten Element. (Aktuelle Stelle ist 0)
So lange ein Element an der aktuellen Stelle vorhanden ist:
- Wenn das Element an der aktuellen Stelle gelöscht werden soll, dann lösche das Element
- Sonst: Wenn das Element verdoppelt werden soll, dann füge das Element an der aktuellen Stelle noch einmal an. Gehe 2 Elemente weiter.
- Sonst: gehe ein Element weiter

Das kann man auch austesten mit Papier und Stift. Hier rate ich Dir, das wirklich zu üben. Am Anfang ist es schwer, aber mit der Zeit macht man sowas dann problemlos im Kopf. Und es hilft auch, sich das dann besser vorstellen zu können!

Bei sprachlichen Formulierungen muss man so lange verfeinern, bis man auf eine Ebene kommt, die 1:1 in das Programm übersetzt werden kann. Und das geht dann mit dem Text oben schon sehr gut. (Das mit dem lower case haben wir da nicht ... aber das ignorieren wir mal einfach ...)
Java:
    public static ArrayList<String> correct(ArrayList<String> liste) {
        int index = 0;
        while (index < liste.size()) {
            String currentElement = liste.get(index).toLowerCase();
            if (!currentElement.contains("l") && currentElement.contains("r")) {
                liste.remove(index);
            } else if (currentElement.contains("l") && !currentElement.contains("r")) {
                liste.add(index, liste.get(index));
                index = index + 2;
            } else {
                index++;
            }
        }
        return liste;
    }
Besten Dank. Habe Ihre Variante ausprobiert. Ja, ich glaube mein Problem hier war, dass ich bei der Inkrementierung nicht richtig verstanden habe, bei welcher Operation ich wieviel Schritt nach vorne gehen soll.

Oder das Einfachste mit zweiter Liste. Das war aber als Musterlösung schon parat, ich wollte etwas anderes coden.

Papier und Stift sind immer gut, da sieht man zumindest, ob man für das Programmieren überhaupt was taugt. Wenn man für relativ einfache Aufgaben kein Algorithmus finden kann ...

Das kommt bestimmt mit der Zeit und Übung.
 

betatwo

Mitglied
Die Lösung mit einer neuen Liste war auch als "Musterlösung" vorhanden
Ich weiß, idR erstelle ich Musterlösungen für andere Studis...

Dem Vorschlag von kneitzel würde ich nicht folgen, weil die Indexerhöhung um 2 unübersichtlich ist und keinen Mehrwert bietet. Zum Üben und Lernen und um Verständnis zu generieren ist es okay, aber nicht in einem echten Code-Review ...
 
Ich weiß, idR erstelle ich Musterlösungen für andere Studis...

Dem Vorschlag von kneitzel würde ich nicht folgen, weil die Indexerhöhung um 2 unübersichtlich ist und keinen Mehrwert bietet. Zum Üben und Lernen und um Verständnis zu generieren ist es okay, aber nicht in einem echten Code-Review ...
Ich als Anfänger kann sowieso nur in seltensten Fällen meinen eigenen code als effizient beschreiben, d.h. weniger Codezeilen, weniger Speicher beansprucht, übersichtlich und selbsterklärend und hauptsache es liefert genau das, was es gemäß der Aufgabenstellung liefern soll.

Und was die Datenstrukturen angeht, da stehe ich immer noch hauptsächlich bei Arrays und Listen, von den anderen in Collections enthaltenen kenne ich nur die Theorie.

Es kommt noch einiges auf mich zu 😄
 
K

kneitzel

Gast
Das war auch in keiner Weise als Musterlösung gedacht sondern sollte lediglich aufzeigen, dass der Ansatz auch problemlos umgesetzt werden kann.

Die Index-Erhöhung ist aber so nicht wirklich intuitiv, weshalb ich die Lösung auch nicht bevorzuge. Man muss sich nur eine Lösung vorstellen, bei der dS sauber untergliedert wurde. Dann sind die Bedingungen in einer Variable (Prädicate<String>) oder in einer Methode ....

Dann hat man Code, der sich super liest:
Wenn Ignoriere Element, dann nichts.
Sonst wenn Verdoppelung Element: fügen Element hinzu, füge Element hinzu
Sonst fügen Element hinzu

Code würde sich fast 1:1 in Java so lesen lassen.
 
K

kneitzel

Gast
Bitte gut aufpassen: es geht nicht um höchste Effizienz! Es geht nicht um wenig Zeilen Code!

Also in dem Bereich nicht optimieren. (Wenn Optimierungen notwendig sind, dann nur mit Analyse und genauem Plan!)

Statt dessen muss Code wartbar sein. Das hat die höchste Priorität! Und da sind paar Zeilen mehr oft Gold wert. Ich bin nicht mehr am Rechner, aber ich kann morgen vielleicht mal meine 'Musterlösung' vorstellen. Wird für die Aufgabe fast Overkill werden fürchte ich, weil halt gewisse Dinge ausgegliedert werden. Aber es geht um die Lesbarkeit, Wartbarkeit, Wiederverwendbarkeit.
 

mihe7

Top Contributor
Wie wusste schon Bob Marley zu berichten? No index, no cry (oder so ähnlich):
Java:
    public static ArrayList<String> correct(ArrayList<String> liste) {
        ListIterator<String> it = liste.listIterator();
        while (it.hasNext()) {
            String element = it.next();
            String currentElement = element.toLowerCase();
            if (!currentElement.contains("l") && currentElement.contains("r")) {
                it.remove();
            } else if (currentElement.contains("l") && !currentElement.contains("r")) {
                it.add(element);
            }
        }
        return liste;
    }
 
K

kneitzel

Gast
Jetzt konnte ich nicht schlafen und habe mich noch einmal an den Rechner gesetzt.

Da ist mir jetzt erst einmal aufgefallen: Von der Signatur her würde ich erwarten, dass die Liste selbst nicht verändert wird, denn es wird ja eine Liste zurück gegeben!

Und dann bin ich ein Fan davon, Dinge immer etwas aufzuteilen. Methoden dürfen nie zu lang werden, damit die Übersicht da ist und die Bezeichner alles gut "dokumentieren".

Die erste Lösung, die ich präsentiere, ist aber jetzt erst einmal mit Streams. Die Streams sind hier aber nicht das Wichtige, sondern schlicht das Vorgehen, wie ich sowas machen würde ... Und ich bringe hier jetzt erst einmal einiges an Design Aspekten mit rein. Das verwirrt Dich hoffentlich nicht zu sehr - Die ganzen Details musst Du nicht zwingend verstehen. Aber ich will es mal angesprochen haben.
Hinweis: Die Namen der Bezeichner sind ein schneller Entwurf in einem müden Zustand. Das müsste bearbeitet werden!

a) Signatur der Methode angepasst. ArrayList ist eine konkrete List. Aber vielleicht wollen wir nicht immer mit ArrayList arbeiten? Daher macht es Sinn, gegen Interfaces zu entwickeln. Wir machen aus ArrayList fast überall ein List (nur in der main bleibt es an einer Stelle - beim new):
Java:
    public static List<String> correct(List<String> liste) {
        // ...
    }

b) wir wollen nun mit jedem Element etwas machen ... das geht über Streams ... Also etwas wie:
liste.stream().machWas().sammelErgebnis().
stream liefert einen Stream von String. Das machWas muss aus jedem Element 0...n Elemente machen können -> flatMap. (Das im Detail zu erläutern sprengt den Rahmen, aber Stream hat nur begrenzt Möglichkeiten - da muss man nur das Passende finden.) Und flatMap muss mit einem Element etwas machen - das machen wir in einer Methode. Somit haben wir hier .flatMap(Test::correctElement)
Ergebnis sammeln - wir wollen eine Liste, also reicht schon ein toList();
Java:
    public static List<String> correct(List<String> liste) {
        return liste.stream()
                .flatMap(Test::correctElement)
                .toList();
    }

flatMap will jetzt ein Element übergeben (String) und will ein Stream<T> zurück, wobei dann auch ein Stream<T> entsteht. Wir wollen am Ende String Elemente haben, also ist die Methode einfach vom Rahmen her:
Java:
    public static Stream<String> correctElement(final String element) {
        // ...
    }

Und nun haben wir diverse Dinge zu prüfen: ignoreElement -> nichts, doubleElement -> Element zwei mal und sonst nur ein Element:
Java:
    public static Stream<String> correctElement(final String element) {
        if (ignoreElement(element)) return Stream.empty();
        if (doubleElement(element)) return Stream.of(element, element);
        return Stream.of(element);
    }

Dann fehlen noch die ignoreElement / doubleElement Methoden:
Java:
    public static boolean ignoreElement(final String element) {
        String lowercaseElement = element.toLowerCase();
        return !lowercaseElement.contains("l") && lowercaseElement.contains("r");
    }
    
    public static boolean doubleElement(final String element) {
        String lowercaseElement = element.toLowerCase();
        return lowercaseElement.contains("l") && !lowercaseElement.contains("r");
    }

Das wäre dann recht schnell eine einfache kleine Lösung, die man so runter schreiben kann.

Die Klasse (Test) sieht dann so aus:
Java:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class Test {
    public static void main(String[] args) {
        List<String> liste = new ArrayList<>();
        liste.add("Rose");
        liste.add("Lilly");
        liste.add("Lora");
        liste = correct(liste);

        for (String s : liste) {
            System.out.println(s);
        }
    }

    public static boolean ignoreElement(final String element) {
        String lowercaseElement = element.toLowerCase();
        return !lowercaseElement.contains("l") && lowercaseElement.contains("r");
    }
    
    public static boolean doubleElement(final String element) {
        String lowercaseElement = element.toLowerCase();
        return lowercaseElement.contains("l") && !lowercaseElement.contains("r");
    }
    
    public static Stream<String> correctElement(final String element) {
        if (ignoreElement(element)) return Stream.empty();
        if (doubleElement(element)) return Stream.of(element, element);
        return Stream.of(element);
    }

    public static List<String> correct(List<String> liste) {
        return liste.stream()
                .flatMap(Test::correctElement)
                .toList();
    }
}

Was ich hier zeigen wollte ist das Vorgehen: Code bleibt immer einfach. Und man packt Dinge immer schön in Methoden (oder Klassen).

Das hier Streams verwendet wurden, spielt keine Rolle. Bei Streams fällt es einfacher, Methoden zu erstellen meine ich, da man Code ungerne in ( ) placken will.

Aber das geht genauso ganz ohne Streams:
Da hat man dann halt so einen Ansatz;
Java:
    public static List<String> correct(List<String> liste) {
        List<String> result = new ArrayList<>();
        // ...
        return result;
    }

Was muss man machen? Für jedes Element prüfen, wie oft das Element vorkommen soll. Und dann die Anzahl der Elemente einfügen:
Java:
    public static List<String> correct(List<String> liste) {
        List<String> result = new ArrayList<>();
        for (String element: liste) {
            int count = getCountForElement(element);
            insert(result, count, element);
        }
        return result;
    }
Das bietet dann auch sehr viel Raum für Änderungen. Mir fallen da direkt mehrere Alternativen ein, die alle Vor- / Nachteile haben. Das ist aber auch nicht das Thema. Ich will wirklich nur auf die Unterteilung in Schritte. Und damit liest es sich fast wie Text.

Artikel artikel = getNextArticle(javaForum);
leser.lies(artikel);
if (leser.hatVerstanden(artikel)) artikel.gibPositiveBewertung();
else javaForum.postReply(artikel, leser.getFragen(artikel));

Das könnte so Java Code sein. Und da ist nichts cryptisches ...

Ich hoffe, ich konnte meinen Punkt etwas verdeutlichen.
 
Jetzt konnte ich nicht schlafen und habe mich noch einmal an den Rechner gesetzt.

Da ist mir jetzt erst einmal aufgefallen: Von der Signatur her würde ich erwarten, dass die Liste selbst nicht verändert wird, denn es wird ja eine Liste zurück gegeben!

Und dann bin ich ein Fan davon, Dinge immer etwas aufzuteilen. Methoden dürfen nie zu lang werden, damit die Übersicht da ist und die Bezeichner alles gut "dokumentieren".

Die erste Lösung, die ich präsentiere, ist aber jetzt erst einmal mit Streams. Die Streams sind hier aber nicht das Wichtige, sondern schlicht das Vorgehen, wie ich sowas machen würde ... Und ich bringe hier jetzt erst einmal einiges an Design Aspekten mit rein. Das verwirrt Dich hoffentlich nicht zu sehr - Die ganzen Details musst Du nicht zwingend verstehen. Aber ich will es mal angesprochen haben.
Hinweis: Die Namen der Bezeichner sind ein schneller Entwurf in einem müden Zustand. Das müsste bearbeitet werden!

a) Signatur der Methode angepasst. ArrayList ist eine konkrete List. Aber vielleicht wollen wir nicht immer mit ArrayList arbeiten? Daher macht es Sinn, gegen Interfaces zu entwickeln. Wir machen aus ArrayList fast überall ein List (nur in der main bleibt es an einer Stelle - beim new):
Java:
    public static List<String> correct(List<String> liste) {
        // ...
    }

b) wir wollen nun mit jedem Element etwas machen ... das geht über Streams ... Also etwas wie:
liste.stream().machWas().sammelErgebnis().
stream liefert einen Stream von String. Das machWas muss aus jedem Element 0...n Elemente machen können -> flatMap. (Das im Detail zu erläutern sprengt den Rahmen, aber Stream hat nur begrenzt Möglichkeiten - da muss man nur das Passende finden.) Und flatMap muss mit einem Element etwas machen - das machen wir in einer Methode. Somit haben wir hier .flatMap(Test::correctElement)
Ergebnis sammeln - wir wollen eine Liste, also reicht schon ein toList();
Java:
    public static List<String> correct(List<String> liste) {
        return liste.stream()
                .flatMap(Test::correctElement)
                .toList();
    }

flatMap will jetzt ein Element übergeben (String) und will ein Stream<T> zurück, wobei dann auch ein Stream<T> entsteht. Wir wollen am Ende String Elemente haben, also ist die Methode einfach vom Rahmen her:
Java:
    public static Stream<String> correctElement(final String element) {
        // ...
    }

Und nun haben wir diverse Dinge zu prüfen: ignoreElement -> nichts, doubleElement -> Element zwei mal und sonst nur ein Element:
Java:
    public static Stream<String> correctElement(final String element) {
        if (ignoreElement(element)) return Stream.empty();
        if (doubleElement(element)) return Stream.of(element, element);
        return Stream.of(element);
    }

Dann fehlen noch die ignoreElement / doubleElement Methoden:
Java:
    public static boolean ignoreElement(final String element) {
        String lowercaseElement = element.toLowerCase();
        return !lowercaseElement.contains("l") && lowercaseElement.contains("r");
    }
  
    public static boolean doubleElement(final String element) {
        String lowercaseElement = element.toLowerCase();
        return lowercaseElement.contains("l") && !lowercaseElement.contains("r");
    }

Das wäre dann recht schnell eine einfache kleine Lösung, die man so runter schreiben kann.

Die Klasse (Test) sieht dann so aus:
Java:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class Test {
    public static void main(String[] args) {
        List<String> liste = new ArrayList<>();
        liste.add("Rose");
        liste.add("Lilly");
        liste.add("Lora");
        liste = correct(liste);

        for (String s : liste) {
            System.out.println(s);
        }
    }

    public static boolean ignoreElement(final String element) {
        String lowercaseElement = element.toLowerCase();
        return !lowercaseElement.contains("l") && lowercaseElement.contains("r");
    }
  
    public static boolean doubleElement(final String element) {
        String lowercaseElement = element.toLowerCase();
        return lowercaseElement.contains("l") && !lowercaseElement.contains("r");
    }
  
    public static Stream<String> correctElement(final String element) {
        if (ignoreElement(element)) return Stream.empty();
        if (doubleElement(element)) return Stream.of(element, element);
        return Stream.of(element);
    }

    public static List<String> correct(List<String> liste) {
        return liste.stream()
                .flatMap(Test::correctElement)
                .toList();
    }
}

Was ich hier zeigen wollte ist das Vorgehen: Code bleibt immer einfach. Und man packt Dinge immer schön in Methoden (oder Klassen).

Das hier Streams verwendet wurden, spielt keine Rolle. Bei Streams fällt es einfacher, Methoden zu erstellen meine ich, da man Code ungerne in ( ) placken will.

Aber das geht genauso ganz ohne Streams:
Da hat man dann halt so einen Ansatz;
Java:
    public static List<String> correct(List<String> liste) {
        List<String> result = new ArrayList<>();
        // ...
        return result;
    }

Was muss man machen? Für jedes Element prüfen, wie oft das Element vorkommen soll. Und dann die Anzahl der Elemente einfügen:
Java:
    public static List<String> correct(List<String> liste) {
        List<String> result = new ArrayList<>();
        for (String element: liste) {
            int count = getCountForElement(element);
            insert(result, count, element);
        }
        return result;
    }
Das bietet dann auch sehr viel Raum für Änderungen. Mir fallen da direkt mehrere Alternativen ein, die alle Vor- / Nachteile haben. Das ist aber auch nicht das Thema. Ich will wirklich nur auf die Unterteilung in Schritte. Und damit liest es sich fast wie Text.

Artikel artikel = getNextArticle(javaForum);
leser.lies(artikel);
if (leser.hatVerstanden(artikel)) artikel.gibPositiveBewertung();
else javaForum.postReply(artikel, leser.getFragen(artikel));

Das könnte so Java Code sein. Und da ist nichts cryptisches ...

Ich hoffe, ich konnte meinen Punkt etwas verdeutlichen.
👍 Vielen lieben Dank für Ihren sehr ausführlichen Beitrag. Die eigentliche "Musterlösung", die in dem OnlineKurs (wo ich übe) präsentiert ist, ist Ihrer Vorgehensweise sehr ähnlich. Ich weiß halt nicht, ob ich diese Lösung einfach so posten und reposten darf, keine Ahnung, ob die privacy dan verletzt wird oder nicht.

Aber es sieht richtig simpel aus:
1) Die Bedingungen fürs Verdoppeln und Entfernen werden in 2 boolean - Var. gepackt.
2) Eine zweite List wird erstellt und,
3) entsprechend den Bedingungen werden Elemente in die zw. List kopiert. Punkt.

Das ist wirklich die einfachste Lösung, zumindest für mich mit meinem Kenntnissstand.

Danke nochmals.
 
K

kneitzel

Gast
Ich weiß halt nicht, ob ich diese Lösung einfach so posten und reposten darf
Ich wäre damit auch eher vorsichtig. Wobei ich bei so Musterlösungen noch nicht sehe, dass da eine gewisse "Schöpfungshöhe" erreicht ist. Aber man sollte versuchen, Anderen nicht auf die Füße zu treten.

Und schön, dass da ein ähnliches Vorgehen gewählt war. Das ist ein Vorgehen, das ich dir auch nur ans Herz legen kann. Das vereinfacht die Entwicklung wirklich ungemein.
 
Ich wäre damit auch eher vorsichtig. Wobei ich bei so Musterlösungen noch nicht sehe, dass da eine gewisse "Schöpfungshöhe" erreicht ist. Aber man sollte versuchen, Anderen nicht auf die Füße zu treten.

Und schön, dass da ein ähnliches Vorgehen gewählt war. Das ist ein Vorgehen, das ich dir auch nur ans Herz legen kann. Das vereinfacht die Entwicklung wirklich ungemein.
Tja, ich kann manchmal nur staunen, wie einfach und verständlich die Lösungen für Aufgaben sind, an denen ich mir stundenlang die Zähne ausbeißen kann.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
R Liste in Variable speichern Java Basics - Anfänger-Themen 6
R Liste und Arrays Java Basics - Anfänger-Themen 12
D 2 ArrayListen gleich sortieren bzw. eine Liste anhand einer anderen Sortieren Java Basics - Anfänger-Themen 6
J Ähnlichen String in Liste finden Java Basics - Anfänger-Themen 6
M Verkettete Liste Java Basics - Anfänger-Themen 1
M Vergleichen, ob eine Liste länger als andere ist Java Basics - Anfänger-Themen 6
H Liste nach String-Länge sortieren Java Basics - Anfänger-Themen 1
D remove Object von einer Liste von Obejcts Java Basics - Anfänger-Themen 3
E Elemente aus Liste entfernen und hinzufügen Java Basics - Anfänger-Themen 3
M Nullpointer beim befüllen meiner Liste im Object Java Basics - Anfänger-Themen 3
D Länge einer Liste aufrufen. Java Basics - Anfänger-Themen 19
B Objekt aus generalisierter Liste entfernen Java Basics - Anfänger-Themen 11
H Liste Knoten NullPointerException Java Basics - Anfänger-Themen 7
W Liste mit Listen in JTable darstellen Java Basics - Anfänger-Themen 1
N Was Passiert mit dem Namen einer Variable, wenn man diese einer Liste Hinzufügt Java Basics - Anfänger-Themen 16
E Suchfunktion in einer Liste Java Basics - Anfänger-Themen 39
T ungeordnete Werte-Paare in einer Liste Java Basics - Anfänger-Themen 7
L Hilfe! Liste mit Items werden ausgegeben aber nicht in zufälliger Reihenfolge Java Basics - Anfänger-Themen 6
berserkerdq2 Warum soll ich shuffle nutzen, um bei Rückgabewert Collection eine Liste zurückzugeben? Java Basics - Anfänger-Themen 3
sserio Wieso werden nicht alle Primzahlen bis 1000 in meine Liste gepackt ? Java Basics - Anfänger-Themen 8
sserio Liste erstellt und ein Problem mit dem Index Java Basics - Anfänger-Themen 8
f3mys Objektwerte in Liste speichern und wieder abrufen Java Basics - Anfänger-Themen 23
H Java verkettete Liste, Wert eines Index zurückgeben Java Basics - Anfänger-Themen 1
K Warum ist die binäre Suche bei der verketteten Liste nicht so effektiv? Java Basics - Anfänger-Themen 3
I 2D-Array Position der Liste ausgeben. Java Basics - Anfänger-Themen 2
I Liste von Infos von einer eigenen Annotation in Liste speichern Java Basics - Anfänger-Themen 0
P Doppelte werte in einer Liste zählen Java Basics - Anfänger-Themen 11
Dorfschmied Kartesisches Produkt von zwei Liste mit Hashmaps<String,String> erstellen Java Basics - Anfänger-Themen 4
Igig1 Autoparkplatz verkettete Liste erstes und letztes Auto Java Basics - Anfänger-Themen 13
thor_norsk Verkette Liste Java Basics - Anfänger-Themen 27
R Rückgabe: verkettete Liste Java Basics - Anfänger-Themen 2
R einfach verkettete Liste Java Basics - Anfänger-Themen 1
R einfach verkettete Liste Java Basics - Anfänger-Themen 12
O Doppelt verkette Liste Element löschen Java Basics - Anfänger-Themen 15
B GUI extension mit einer Liste verbinden Java Basics - Anfänger-Themen 1
B Verkettete Liste durchgehen und einzelne Elemente in neue Liste tun Java Basics - Anfänger-Themen 9
B Bin komplett am verzweifeln :( Verkettete Liste die Objekte hat Attribut auslesen Java Basics - Anfänger-Themen 14
M Java Liste streamen Java Basics - Anfänger-Themen 10
AmsananKING Aussortierung einer Liste Java Basics - Anfänger-Themen 8
A Objekte mit Parametern in eine Liste packen Java Basics - Anfänger-Themen 19
S Kann nicht auf die Liste zugreifen mit der Methode!? Java Basics - Anfänger-Themen 3
B Datentyp für Einzelnes Objekt oder Liste Java Basics - Anfänger-Themen 9
alice98 Erste Schritte Liste erstellen ohne vorgefertigte Klassen Java Basics - Anfänger-Themen 1
J Doppelt verkette Liste ich bitte um Hilfe Java Basics - Anfänger-Themen 4
I Liste gruppieren nach Monat? Java Basics - Anfänger-Themen 5
districon Element in Liste einfügen Java Basics - Anfänger-Themen 1
B Hilfe bei Map Liste erstellen Java Basics - Anfänger-Themen 10
Y Einfügen in eine doppelt verkettete Liste Java Basics - Anfänger-Themen 8
Y Knoten an einem gegebenen Index aus einer Liste entfernen. Java Basics - Anfänger-Themen 6
H Daten aus einer Datei in eine Liste speichern Java Basics - Anfänger-Themen 23
Gaudimagspam Linked Liste Java Basics - Anfänger-Themen 4
Z Liste umkehren Java Basics - Anfänger-Themen 1
S Eine Liste kopieren Java Basics - Anfänger-Themen 13
java3690 Java- liste füllen ud die werte addieren Java Basics - Anfänger-Themen 13
java3690 Liste mit zufälligen zahlen füllen Java Basics - Anfänger-Themen 27
java3690 eine liste sortieren Java Basics - Anfänger-Themen 12
J Element aus Liste nehmen Java Basics - Anfänger-Themen 3
B JUnit 4: Wie man die eigene Liste testen kann [TDD] Java Basics - Anfänger-Themen 46
B Interface List - Objekt übergeben? Einzelnes Objekt geht, aber Liste nicht? Java Basics - Anfänger-Themen 4
P Was genau bringt mir es ein Array in eine Liste zu bringen Java Basics - Anfänger-Themen 3
A Doppelt verkettete Liste rückwärts ausgeben Java Basics - Anfänger-Themen 17
P Verschachtelte Array Liste Java Basics - Anfänger-Themen 2
H Liste speichern. Was lässt sich verbessern? Java Basics - Anfänger-Themen 7
P Performance Array und Liste Java Basics - Anfänger-Themen 13
M QuickSort und Liste Java Basics - Anfänger-Themen 6
N Methode um Objekte einer Liste hinzuzufügen Java Basics - Anfänger-Themen 1
B Summe von Property innerhalb einer Liste via Lambda Java Basics - Anfänger-Themen 1
V Collections int Werte in einer Liste sortieren Java Basics - Anfänger-Themen 23
B Neue Liste erstellen, wenn Objekte bestimmte Referenz hat / Gruppierung von Einträgen Java Basics - Anfänger-Themen 12
V_Fynn03 Beliebiges Element in einer Liste löschen (Java)(Lineare Datenstrukturen) Java Basics - Anfänger-Themen 9
L Baum aus Integer Liste erstellen Java Basics - Anfänger-Themen 0
CptK Koordinate in Liste suchen Java Basics - Anfänger-Themen 20
C Verschiedene Objekte in einer Liste speichern Java Basics - Anfänger-Themen 6
M Ausgabe einer Liste welche mehrere Stacks enthält Java Basics - Anfänger-Themen 3
D Doppelt Verkettete Zirkular-Liste Java Basics - Anfänger-Themen 1
L Liste in anderem Thread laden Java Basics - Anfänger-Themen 1
M Array liste Verdrehen Java Basics - Anfänger-Themen 8
A Verkettete Liste Java Basics - Anfänger-Themen 2
J Strings untereinander in einer Liste vergleichen Java Basics - Anfänger-Themen 18
B Liste von Tagen generieren ab einem bestimmten Datum und Endedatum Java Basics - Anfänger-Themen 4
S IndexOutOfBoundsException beim hinzufügen eines Elements zu einer Liste Java Basics - Anfänger-Themen 11
B Liste sortieren? Java Basics - Anfänger-Themen 4
O Anonyme Klasse einer Liste erstellen Java Basics - Anfänger-Themen 7
B SWAP List; Liste neu anordnen Java Basics - Anfänger-Themen 4
B CSS Klassen in eine Liste schreiben Java Basics - Anfänger-Themen 4
B Doppelt verkettete Liste implementieren Java Basics - Anfänger-Themen 8
L verkettete Liste Java Basics - Anfänger-Themen 15
scratchy1 doppelt verkettete Liste testen Java Basics - Anfänger-Themen 8
O ADT Liste z. B. Java Basics - Anfänger-Themen 15
B sortierte Liste Java Basics - Anfänger-Themen 4
O Knoten und Liste verarbeitung Java Basics - Anfänger-Themen 20
R Methoden Entferne alle identische Knoten (Typ String) aus verkettete Liste Java Basics - Anfänger-Themen 8
C Methoden Über eine einfach verkettete Liste Java Basics - Anfänger-Themen 8
J Eine Liste von Listen erstellen Java Basics - Anfänger-Themen 11
A Einträge aus Tupeln nach Regeln in Liste speichern Java Basics - Anfänger-Themen 8
Queiser Liste zurückgeben Java Basics - Anfänger-Themen 7
T Collections Geeignete Collection/Liste/Datenbank Java Basics - Anfänger-Themen 17
S spezielle Wörter aus Liste entfernen Java Basics - Anfänger-Themen 2
H Verkettete Liste Java Basics - Anfänger-Themen 7
E Elemente aus Liste löschen Java Basics - Anfänger-Themen 5

Ähnliche Java Themen

Neue Themen


Oben