2 Stimmen

Wie kann ich eine Liste von Hash-Referenzen aus einer Map in Perl zurückgeben?

Ich habe den folgenden größtenteils in Ordnung befindlichen Code:

my $results = { data => [
   map {
      my $f = $_->TO_JSON;
      $f->{display_field} = $_->display_field($q);
      $f;
   } $rs->all
]};

Nur würde ich es lieber so haben:

my $results = { data => [
   map {
      %{$_->TO_JSON},
      display_field => $_->display_field($q),
   }, $rs->all
]};

Aber das führt zu einem Syntaxfehler. Wie kann ich erreichen, was ich möchte, oder ist meine aktuelle Version das Beste, was es gibt?

Update: Entschuldigung für das extra Semikolon davor. Es ist spät hier. Keine Ahnung, wie mir das entgangen ist. Danke Leute!

7voto

derobert Punkte 47691

Es gibt nur einen Syntaxfehler, weil Ihr Perl denkt, dass Sie das Komma nach map { ... } weglassen müssen, weil es diese Karte als Block verarbeitet und nicht als Ausdruck. Das Hinzufügen von + davor wird das beheben. Außerdem können Sie kein Semikolon in einem anonymen Hash haben:

my $ergebnisse = { daten => [
   map +{
#      ^----------------- Pluszeichen hinzugefügt
      %{$_->TO_JSON},
      anzeigefeld => $_->anzeigefeld($q);
#                                           ^---- sollte ein Komma oder nichts sein
   }, $rs->all
]};

3voto

Chris Lutz Punkte 69879

Das Problem ist, dass Perl nicht weit genug vorausschaut, um herauszufinden, ob { bedeutet "starten Sie eine anonyme Hasenreferenz" oder "starten Sie einen Codeblock". Es sollte (idealerweise) zum entsprechenden } schauen und sehen, ob ein Komma vorhanden ist oder nicht, und entsprechend handeln, tut es aber nicht. Es schaut nur ein wenig voraus und versucht zu raten. Und dieses Mal liegt es falsch, und Sie erhalten einen Syntaxfehler über ein Komma, das dort nicht sein sollte, außer dass es das schon sollte, also bewegen Sie es nicht.

perldoc -f map wird Ihnen alles darüber sagen. Grundsätzlich besagt es, dass wenn Sie +{ schreiben, wird Perl verstehen, dass dies "kein Codeblock" bedeutet und vermuten, dass es sich um eine Hasenreferenz handelt. Das ist wahrscheinlich die Ursache für Ihren Syntaxfehler. Als weiterer Vorschlag könnte es funktionieren zu sagen map({ HASH STUFF }, $rs->all) - Ich wette, dass Perl hier nicht erraten wird, dass es sich um eine Code-Referenz handelt.

Ich konnte es nicht zum Laufen bringen, aber ohne $rs oder ein ->TO_JSON oder eine Variable namens $q konnte ich sowieso nichts davon zum Laufen bringen. Ich hoffe, das hilft. Wenn nicht, posten Sie ein wenig mehr Code. Keine Sorge, wir beißen nicht.

Und übrigens, während wir schon dabei sind, warum nicht auf diese Weise schreiben:

my $ergebnisse;
$ergebnisse->{daten} = [ map MAGIC MAP STUFF, $rs->all ];

Könnte argumentiert werden, dass es leserlicher ist, besonders wenn Sie viele Dinge auf einmal zu $ergebnisse hinzufügen.

1voto

friedo Punkte 64178

Ich bin mir nicht ganz sicher, nach welcher Art von Struktur Sie suchen. Die map in Ihrem ersten Beispiel gibt bereits eine Liste von Hash-Referenzen zurück (jede Version von $f).

Wenn Sie nur eine Syntax ähnlich Ihrem zweiten Beispiel möchten, dann lagen Sie fast richtig; Sie müssen das überflüssige Semikolon in Ihrem Kartenblock loswerden und ein Paar Klammern verwenden, um eine anonyme Hash-Referenz zu erstellen.

So etwas wie:

my $results = { data => [
    map { { %{$_->TO_JSON},
            display_field => $_->display_field($q)
          }
    } $rs->all
]};

0voto

brian d foy Punkte 124323

Ich verwende immer die map im Blockform, und strukturiere den Code so, dass er leicht zu durchschauen ist. Obwohl Sie ein + vor der öffnenden geschweiften Klammer setzen können, um die Ausdrucksform zu verwenden, ist es Ihnen wirklich so wichtig?

Abgesehen von allem anderen, sieht Ihr erstes Beispiel gut aus. Machen Sie weiter und lösen Sie echte Probleme. :)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X