Wie iteriere ich durch ein Array in einem Raku-Hash?

8

Dies scheint eine einfache Frage zu sein, aber Perl6 / Raku verhält sich nicht so, wie ich es erwarten würde. Ich versuche, einen Verweis auf ein Array innerhalb eines Hashs zu erstellen, erhalte jedoch nicht das erwartete Verhalten. In Perl5 würde die Antwort den Zugriff auf das Array als Referenz beinhalten, aber ich sehe keine äquivalente Syntax für Perl6 / Raku.

my $jsonstr = q:to/END/;
{
    "arr" : [
        "alpha","beta","delta","gamma"
    ]
}
END

my %json = from-json $jsonstr;
my @arr = %json{'arr'};
say "Arr length is " ~ @arr.elems; # Expect 4, get 1
say "Orig length is " ~ %json{'arr'}.elems; # Get expected value of 4
say "Arr[0] is " ~@arr[0].^name ~ " of length " ~ @arr[0].elems; # First index is array

say %json{'arr'}[0]; # Indexing into array in original location works as expected
say @arr[0][0]; # But when assigned, it needs an extra index

my @arr2 = @arr[0]; # Same issue in re-assignment here
say "Arr2[0]: " ~ @arr2[0] ~ ", length of " ~ @arr2.elems;

Wie erhalte ich eine neue @ arr-Variable, um auf das verschachtelte Array zu verweisen, ohne diese verwirrende zusätzliche [0] Indexebene? Ist das ein Fehler oder fehlt mir etwas in meinem Verständnis von Rakus Array / Ref-Handhabung? Vielen Dank.

Digicrat
quelle

Antworten:

7

Wenn Sie arrdem Array den Wert im Schlüssel zuweisen @arr, nimmt er den Wert, in %json{'arr'}dem sich das Array-Objekt befindet, ["alpha","beta","delta","gamma"]und fügt ihn ein, @arrsodass Sie ein Array von Arrays mit 1 Element erhalten.

Sie haben einige Möglichkeiten:

Sie können binden @arran %json{"arr"}mitmy @arr := %json{"arr"}

Oder Sie können das %json{"arr"}an eine Liste mit übergebenmy (@arr) = %json{"arr"}

Sie müssen sich daran erinnern, dass Raku Arrays Objekte sind.

Scimon Proctor
quelle
5
Unter Leistungsgesichtspunkten ist die my @arr := %json<arr>Lösung am besten geeignet, da weder Werte kopiert noch zusätzliche Objekte erstellt werden müssen.
Elizabeth Mattijsen
2

Wie üblich habe ich nach dem Schreiben + Posten meiner Frage meine eigene Frage beantwortet.

my @arr = %json{'arr'}.Array;

Ich verstehe nicht ganz, warum dies notwendig ist, aber es gibt das gewünschte Verhalten.

Digicrat
quelle
3
%json{'arr'}ist ein Skalar (denken Sie, Verweis auf ein Array). Wenn Sie die Array-Methode aufrufen, wird der Skalar "dereferenziert", oder genauer gesagt, der Skalarinhalt aus seinem Skalarcontainer wird in einen Listencontainer eingefügt. Sie hätten auch schreiben können %json{'arr'}.flatoder |%json{'arr'}, obwohl ich denke, dass die ArrayMethode in diesem Fall etwas schneller ist.
Holli
1
Ausarbeiten. In Raku werden Arrays und Listen nicht automatisch abgeflacht. Daher my @a = (1,2), (3,4)wird ein Array von Listen mit zwei Elementen erstellt, kein Array von Ints mit vier.
Holli
2
Raku hat keine Referenzen, es hat nur unveränderliche Werte und Container. Ihre Lösung führt Folgendes aus: 1. Erzwingen Sie das ArrayObjekt im Hash zu einem Array: Dies ist für sich genommen ein Noop, aber was noch wichtiger ist, es verliert den Container, in dem das Array im Hash gespeichert wurde. Da das ArrayObjekt iterierbar ist, kopiert es seine Werte in das @arrArray und erledigt möglicherweise eine Menge unnötiger Arbeit für große Arrays.
Elizabeth Mattijsen