Frage Perl6: Ordnet Elemente in einer Liste einer anderen Liste zu


Ich habe eine Liste von Zahlen L. Es gibt eine andere Liste von Zahlen M. Ich muss eine Liste zurückgeben L ' von Zahlen gefunden in beide  L und M.

Bearbeiten: Mathematisch suche ich Multiset Überschneidung.

Beispiel:

L  = 3, 14, 15, 9, 2, 6
M  = 97, 1, 2, 1, 1
L ' = 9, 1, 2, 1

Ich habe das geschrieben folgender Code dafür:

my @some-numbers = 3, 1, 4, 1, 5, 9, 2, 6;
my @to-match     = 9, 7, 1, 2, 1, 1;
my @matched;

my %histogram;
for @some-numbers -> $n { %histogram{$n}++ };

for @to-match -> $n {
    next if not defined %histogram{$n};
    if %histogram{$n} > 0 {
        push @matched, $n;
        %histogram{$n}--;
    }
};

say @matched;

Während es den Zweck erfüllt, habe ich mich gefragt, ob es ein idiomatisch Perl6 Weg dies zu tun?

Einige Hintergrundinformationen: Ich habe versucht, Perl6 und Python zusammen zu lernen und löse die gleichen Rätsel in beiden Sprachen. Python bot eine besonders an angenehme Lösung für das obige Problem. Für meine Anfängeraugen zumindest :)


5
2018-03-31 19:06


Ursprung


Antworten:


Abhängig von der genauen Semantik, die Sie suchen, Tasche Operationen könnten nur das Ticket sein:

my \L = 3, 1, 4, 1, 5, 9, 2, 6;
my \M = 9, 7, 1, 2, 1, 1;

.put with L.Bag ∩ M.Bag;

zeigt an:

9 1(2) 2

Dies ist die Zeichenfolge von a Bag enthält die drei Schlüssel  '9', '1', und '2' wessen jeweiligen Werte (Wiederholungszählungen) sind die ganzen Zahlen 1, 2, und 1.

Um Perl 6 dazu zu bringen, eine Liste aus einer Tüte zu erstellen, bei der jede Taste die Anzahl der Male wiederholt, die durch den zugehörigen Wert angezeigt wird, verwenden Sie die Taste .kxxv Methode:

.kxxv.put with L.Bag ∩ M.Bag;

zeigt an:

9 1 1 2

(Die Mnemonik für die kxxv Methode ist, dass es ist k für "Schlüssel" dann xx in Analogie zu den xx Wiederholungsoperator und schließlich v für "Wert". Es macht Sinn, wenn Sie darüber nachdenken.)

Aber vielleicht reicht eine Tasche nicht. Zum Beispiel, vielleicht die Reihenfolge der Elemente im Ergebnis zählt - Sie brauchen 9 1 2 1 und nicht 9 1 1 2? Ich werde diese Antwort erweitern, wenn eine Tasche nicht der richtige Weg ist.


6
2018-03-31 22:23



Sie können es mit Taschen tun:

my $some-numbers = bag 3, 1, 4, 1, 5, 9, 2, 6;
my $to-match     = bag 9, 7, 1, 2, 1, 1;
my $matched      = $some-numbers ∩ $to-match;
say $matched;

Ausgabe:

bag(9, 1(2), 2)

Sie können die Tasche wieder in ein Array mit verwandeln .kxxv.

my @match-list = $matched.kxxv;
say @match-list;

Ausgabe:

[9 1 1 2]

(Wenn Duplikate nicht wichtig sind, benutze Sets statt Taschen.)


6
2018-03-31 21:18



Sie können dies versuchen:

use v6;

my @some_numbers = 3, 1, 4, 1, 5, 9, 2, 6;
my @to_match     = 9, 7, 1, 2, 1, 1;
my %seen  = map { $_ => 1 }, @to_match;
my @matched = grep { %seen{$_}:exists }, @some_numbers;
say @matched;

Ausgabe:

[1 1 9 2]

1
2018-03-31 20:39