Versuchen Sie stattdessen Folgendes:
%Vor%Der Grund für Ihre unerwarteten Ergebnisse ist, dass Sie ein leeres Array als Standardwert angegeben haben, aber dasselbe Array verwendet wird; keine Kopie ist fertig. Der richtige Weg ist, den Wert mit einem neuen leeren Array zu initialisieren, wie in meinem Code.
Der -Konstruktor , den Sie verwendet haben, speichert []
als Standardwert für den Zugriff auf unbekannte Schlüssel. Da Array#<<
seinen Empfänger an Ort und Stelle ändert wächst dieses anfänglich leere Array.
Um genauer zu erklären:
Wenn du hash['a'] << 1
machst, passiert Folgendes:
hash
prüft, ob es einen Schlüssel namens 'a'
gibt
Hash.new([])
erstellt haben, hat es einen solchen Wert, []
und gibt das zurück. [] << 1
ausgewertet und dies bedeutet, dass der Hash nun [1]
als Rückgabewert speichert, wenn ein zuvor nicht gefundener Schlüssel angefordert wird. Wenn Sie das Schlüsselwertpaar speichern möchten, verwenden Sie stattdessen die dritte Form des Konstruktors mit einem Block:
%Vor%Dies ist genau das Verhalten, das Sie erwarten würden.
Sie fügen dem Hash
niemals etwas hinzu, daher ist Hash
vollständig leer. Wenn Sie einen Schlüssel nachschlagen, wird dieser Schlüssel niemals existieren. Daher gibt er den Standardwert zurück, den Sie als Array
angegeben haben.
Sie suchen also den Schlüssel 'a'
, der nicht existiert, und geben daher die Array
zurück, die Sie als Standardwert angegeben haben. Dann rufen Sie <<
für Array
auf, wodurch ein Wert ( 1
) an ihn angehängt wird.
Als nächstes suchen Sie den Schlüssel 'b'
, der ebenfalls nicht existiert, und geben daher den Array
zurück, den Sie als Standardwert angegeben haben, der jetzt das zuvor hinzugefügte Element 1
enthält. Dann rufen Sie <<
für diese Array
auf und fügen den Wert 2
hinzu.
Sie haben am Ende ein Hash
, das immer noch leer ist, da Sie nichts hinzugefügt haben. Der Standardwert von Hash
ist jetzt ein Array mit den Werten 1
und 2
.
Die Ausgabe, die Sie sehen, ist, weil IRb immer das Ergebnis des letzten Ausdrucks ausgibt, der ausgewertet wurde. Der letzte Ausdruck in Ihrem Beispiel ruft <<
für Array
auf. <<
gibt seinen Empfänger zurück, der dann der Rückgabewert des gesamten Ausdrucks ist und somit, was IRb ausgibt.