Kann ein Array nicht als Standardwerte für Ruby Hash verwenden? [Duplikat]

8

Ich habe Elemente zu einem Hash-Schlüssel hinzugefügt. Ich hatte erwartet, eine Struktur wie diese zu bekommen:

%Vor%

Ich habe ein Array verwendet, um den Hash zu initialisieren.

%Vor%

Dann begann es zu benutzen:

%Vor%

Aber es stellt sich heraus:

%Vor%     
Cheng 30.03.2011, 16:00
quelle

4 Antworten

11

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.

    
Marc-André Lafortune 30.03.2011, 16:04
quelle
4

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:

  1. hash prüft, ob es einen Schlüssel namens 'a' gibt
  2. Es findet, dass nein, es gibt keinen solchen Schlüssel.
  3. Es sieht so aus, als ob ein Standardwert für die Rückgabe gespeichert wurde.
  4. Da Sie es mit Hash.new([]) erstellt haben, hat es einen solchen Wert, [] und gibt das zurück.
  5. Jetzt wird [] << 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%     
Jakub Hampl 30.03.2011 16:13
quelle
2

hash['a'] << 1 und hash['b'] << 2 ist keine korrekte Syntax zum Erstellen eines Schlüssel / Wert-Paares. Sie müssen = dafür verwenden:

%Vor%

Das sollte Ihnen den Hash {'a' : [1], 'b' : [2]}

geben     
McStretch 30.03.2011 16:04
quelle
1

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.

    
Jörg W Mittag 30.03.2011 16:25
quelle

Tags und Links