• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

[FRAGE] Anagram Verständnisfrage

houseshow

New member
Guten Tag, bin neu hier und hab da eine Verständnisfrage zu einem Anagram Script.
Ich bin noch relativ frisch in javascript unterwegs und dabei es zu lernen. Nun hatte ich die Aufgabe gefunden 2 Strings auf ein Anagram zu prüfen und habe beim googeln nach möglichen Herangehensweisen einige Lösungen gefunden, welche ich zum großen Teil auch weitestgehend nachvollziehen konnte aber aus dieser einen Lösung werde ich einfach nicht schlau. Ich versuche wirklich zu verstehen warum das Script so funktioniert wie es funktioniert aber ich steige einfach nicht dahinter. Ich hoffe mir kann das jemand Anfängerfreundlich erklären, wäre sehr nett :)
Um folgendes Script geht es:

Code:
function Anagrams(str1, str2) {
    if (str1.length !== str2.length) 
        return false;

    let count = {};

    for (let i in str1) {
        count[str1[i]] = (count[str1[i]] || 0) + 1;           
        count[str2[i]] = (count[str2[i]] || 0) - 1;           
    }

    for (let k in count) {
        if (count[k] !== 0)
            return false;
    }

    return true;
}

console.log(Anagrams('abc','abc'))//true
console.log(Anagrams('baaa','bbaa'))//false
console.log(Anagrams('banana','bananas'))//false

Dem part hier kann ich - glaube ich zumindest - noch soweit folgen.

Code:
function Anagrams(str1, str2) {
    if (str1.length !== str2.length) 
        return false;

    let count = {};

Ich lege eine Funktion mit 2 Werten an und prüfe ob die Zeichenlänge beider Strings unterschiedlich ist. Ist die Zeichenlänge unterschiedlich liegt kein Anagram vor also ist das Ergebnis falsch.
Anschließend lege ich ein leeres Objekt an.. soweit so gut...
Danach bin ich raus und kann nicht wirklich folgen.
Wie kommen die einzelnen Buchstaben in das Objekt?
Ich kann soweit folgen das die Anzahl der verschiedenen Buchstaben im 1. String gezählt werden und anschließend jeder Buchstabe der auch im 2. String vorhanden ist wieder subtrahiert wird aber wie gesagt versteh ich schon nicht wo überhaupt die Buchstaben herkommen. Zum anderen versteh ich nicht was das || 0 (oder 0) da genau macht, ich weiß nur das es ohne nicht funktioniert. (Würde sich aber sicher Aufklären wenn ich dem Part davor folgen könnte.
Im letzten Part wird wenn ich es richtig verstanden habe (let k in count) überprüft ob ein Zeichen übrig also nicht 0 ist und die 2 Strings daher kein Anagram sind und deswegen wird Falsch zurückgegeben (Aber auch hier kann ich nicht folgen warum k in dem Fall weiß das es a, b, c etc. ist).

Ich hoffe jemand erbarmt sich und erleuchtet mich. Über nützliche Links evtl. mit Übungsaufgaben etc. wäre ich auch sehr dankbar :)
 
Hi!
Zuerst habe ich mal eine Frage: wie definierst du für diese Aufgabe ein Anagramm? Warum schreibst du es mit nur einem m (gibt es einen Unterschied je nach Schreibweise?) und warum konkret vergleichst du in diesem Zusammenhang zwei Wörter miteinander?
Ich habe ein Anagramm ganz anders im Kopf, daher muss ich fragen.
 
Morgen mikdoe,
ich hatte bei einem Anagramm auch etwas anderes im Kopf aber es handelt sich dabei um eine Buchstabenfolge die durch Umstellung eine andere Buchstabenfolge ergibt. Sprich alle Buchstaben in einem Wort werden anders zusammengesetzt und ergeben ein anderes Wort. (Könnten theoretisch auch Sätze sein.) Ein spontanes Beispiel wäre „Rabe“ ein Anagramm dazu wäre „Aber“. Ich habe lediglich etwas gedenglischt da die Lösung in dem Fall auf englisch war, Bedeutung sollte dieselbe sein, mein Fehler. 2 Wörter vergleiche ich in dem Fall weil dies die Aufgabenstellung war, könnten wie erwähnt auch mehr Wörter/Sätze sein.
Grüße
 
Das Script bestimmt von jedem Buchstaben, wie oft er in str1 vorkommt und zieht davon die Anzahl dieses Buchstabens in str2 ab. Wenn die strings aus den gleichen Buchstaben bestehen, ist dann der count für jeden Buchstaben am Ende 0. Wie ich finde eine äußert komplizierte Herangehensweise.
 
Ich glaube dein Verständnisproblem kommt von den for ... in Schleifen.
Die erste würde ich umschreiben zu for (let i = 0; i < str1.length; i += 1). str1[i] ist dann einfach der (i+1)-te Buchstabe in str1. Und dadurch kommen die Buchstaben in count rein.
Die zweite könnte man mit Object.keys() umschreiben, aber das wäre nicht viel besser verständlich. For...in iteriert hier einfach durch alle Attribute in dem Objekt. Also durch alle Buchstaben in den Strings.

Wenn dir eine Schleife nicht ganz klar ist, kannst du ja einfach ein console.log(i); (bzw. k statt i) auf der Iterationsvariablen in der Schleife machen. Dann siehst du in der Konsole, was das für Werte annimmt. Wenn du noch genauer sehen willst, was bei den einzelnen Schritten passiert, kannst du mit dem Debugger (und entsprechenden Breakpoints) da Schritt für Schritt durchgehen.

Das count[str1[i]] = (count[str1[i]] || 0) + 1; könnte man verständlicher schreiben mit
Code:
if (str[i] in count){
    count[str1[i]] += 1;
}
else {
    count[str1[i]] = 1;
}
 
Vielen lieben Dank kkapsner,

das hat es für mich verständlicher gemacht. Mit console.log hatte ich gearbeitet und gesehen das die Buchstaben und deren Anzahl aufgenommen werden aber das hat mir nicht wirklich geholfen da ich nicht verstanden habe warum das so ist. ^^ Das oder 0 (|| 0) habe ich allerdings leider immernoch nicht verstanden. Da muss ich nochmal drüber nachdenken :)

Danke dir nochmals :)

@Dormilich
Was wäre denn deiner Meinung nach eine bessere Herangehensweise? Ich fand das Script insofern gut/interessant weil es wohl relativ ressourcenschonend ist (ohne join, etc.).
 
Der ||-Operator in JS ist etwas anders als in anderen Sprachen, da er nicht unbedingt ein Boolean zurückgibt, sonder den ersten Parameter, wenn er true-artig ist und ansonsten den zweiten.

Hier ist count[str1[i]] undefined, wenn der Buchstabe noch nicht vorgekommen ist. Das ist false-artig und dadurch ergibt das Konstrukt 0. Wenn der Buchstabe schon einmal vorgekommen ist, wird einfach der Zahlenwert zurückgegeben.

Beispielcode, mit dem man das ev. besser versteht:
Code:
var count = {};
console.log(count["a"]);
console.log(count["a"] || 0);
count["a"] = 1;
console.log(count["a"]);
console.log(count["a"] || 0);
 
Was wäre denn deiner Meinung nach eine bessere Herangehensweise?
Was jedenfalls einfacher zu verstehen wäre, ist String.split, Array.sort, Array.join, String.toLowerCase, String.trim/replace.

Ich fand das Script insofern gut/interessant weil es wohl relativ ressourcenschonend ist (ohne join, etc.).
Auf diesem Level an Arbeit brauchen wir uns keine Gedanken über Ressourcen machen.
 
Zurück
Oben