Frage

Ich sehe die Ergebnisse aus dem folgenden Code, aber ich nicht genau verstehen, wie die or weiß, was in dem folgende sort Beispiel zu tun:

use Data::Dumper;

$animals{'man'}{'name'} = 'paul';
$animals{'man'}{'legs'} = 2;
$animals{'cheeta'}{'name'} = 'mike';
$animals{'cheeta'}{'legs'} = 3;
$animals{'zebra'}{'name'} = 'steve';
$animals{'zebra'}{'legs'} = 4;
$animals{'cat'}{'name'} = '';
$animals{'cat'}{'legs'} = 3;
$animals{'dog'}{'name'} = '';
$animals{'dog'}{'legs'} = 4;
$animals{'rat'}{'name'} = '';
$animals{'rat'}{'legs'} = 5;

@animals = sort {
      $animals{$a}{'name'} cmp $animals{$b}{'name'}
   or $animals{$a}{'legs'} <=> $animals{$b}{'legs'}
} keys %animals;

print Dumper(\@animals);
War es hilfreich?

Lösung

or ist ein Kurzschluss Auswerter, so wird es den Wert der linken Seite zurück, wenn es wahr ist (was jeder Nicht-Null-Wert ist), und wird prüfen, da sonst die rechte Seite.

Also in diesem Fall, wenn die Tiere Namen gleich, ist. (0 - false), wird die Anzahl der Beine zu Sortierzwecken gezählt werden

Andere Tipps

Die sortsub (der Stoff, in {} nach dem sort) einer Zwei-Klassen-Sortierung: zuerst mit Namen, dann nach der Anzahl der Beine. Die or implementiert die Cross-Over zwischen den beiden Kriterien. Es ist einfacher zu sehen, ob Sie den Code formatiert anders:

@animals = sort {
    $animals{$a}{'name'} cmp $animals{$b}{'name'} or
    $animals{$a}{'legs'} <=> $animals{$b}{'legs'}
} keys %animals;

Die cmp und <=> Operatoren liefern einen von drei Werten (-1, 0 oder 1), je nachdem, ob das linke Argument kleiner als, gleich oder größer als das rechte Argument. (cmp hat einen String-Vergleich, <=> hat eine numerische ein.) In Perl, 0 falsch ist, während -1 und 1 wahr sind. Wenn der cmp einen wahren Wert zurückgibt, kehrt der or dieser Wert sofort und sort ordnet die Elemente in geeigneter Weise. Wenn die cmp false zurückgibt, wird die <=> ausgewertet und das Ergebnis wird zurückgegeben, statt.

Wenn die Multi-Layer-Art zu tun, ist es üblich, eine "Karte-Art-Karte" Technik zu verwenden (auch bekannt als Schwartzian Transformation):

@animals =
  map  { $_->[0] }
  sort {
    $a->[1] cmp $b->[1] ||
    $a->[2] <=> $b->[2]
  }
  map { [$_, $animal{$_}{name}, $animal{$_}{legs}] }
  keys %animal;

Es ist nicht so klar, aber da es in der Regel eine bessere Leistung hat es eine gemeinsame Idiom. Dies ist besonders wichtig, wenn die Operanden an die Vergleichsfunktionen sind - diese Technik verhindert eine unnötige (und möglicherweise teuer) Neuberechnung für jeden Vergleich. Zum Beispiel sind, wenn Sie Strings nach Länge Sortierung müssen Sie nur einmal die Länge der einzelnen Strings berechnen.

Darf ich vorschlagen, Sort::Key als Alternative für den vorliegenden Code überhaupt?

use Sort::Key::Multi qw(sikeysort);  # sort keyed on (string, integer)
@animals = sikeysort { $animals{$_}{name}, $animals{$_}{legs} } keys %animals;

# alternately,
use Sort::Key::Maker sort_by_name_then_legs =>
    sub { $animals{$_}{name}, $animals{$_}{legs} }, qw(string integer);
@animals = sort_by_name_then_legs keys %animals;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top