2017-03-31 22 views
5

Ich habe eine Liste von Zahlen L. Es gibt eine andere Liste von Nummern M. Ich muss eine Liste L ' von Zahlen in sowohlL und M zurückgeben.Perl6: Elemente in einer Liste mit einer anderen Liste übereinstimmen

bearbeiten: Mathematisch Ich suche Multiset Kreuzung.

Beispiel:

L = 3, 1, 4, 1, 5, 9, 2, 6
M = 9, 7, 1, 2, 1, 1
L ' = 9, 1, 2, 1

Ich schrieb die following 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 das Ziel erreicht, ich habe mich gefragt, ob ein idiomatischer Perl6 Weg, dies zu tun, da war?

Einige Hintergrund: Ich habe versucht, Perl6 und Python zusammen zu lernen, und lösen Sie die gleichen Rätsel in beiden Sprachen. Python bot eine spezielle pleasing solution für das obige Problem. Um meine Anfänger Augen mindestens :)

+0

Warum gibt es zwei und nicht drei Vorkommen von '1' in' L''? –

+0

In Perl5 können Sie 'my% seen = map {$ _ => 1} @to_match; my @match = grep {exists $ seen {$ _}} @ some_numbers' –

+0

Es tut uns leid, dass ich die Frage nicht genau formuliert habe. Ich erkannte, dass das, wonach ich suchte, die Schnittmenge [Multiset] (https://en.wikipedia.org/wiki/Multiset) war. Ich habe die Problembeschreibung bearbeitet, um das widerzuspiegeln. Danke :) – Anant

Antwort

6

Abhängig von der genauen Semantik, die Sie suchen, könnte Bag Operationen genau das Richtige 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; 

Displays:

9 1(2) 2 

Dies ist die stringification eines Bag die drei enthalten Schlüssel'9', '1' und , deren entsprechende Werte (Wiederholungszählungen) sind die Ganzzahlen 1, 2 und 1.

Um Perl 6 eine Liste aus einem Beutel mit jeder Taste wiederholt, um die Anzahl der Male von seinem zugeordneten Wert ist, verwenden, um die .kxxv angegebene Methode zur Herstellung von:

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

Displays:

9 1 1 2 

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

Aber vielleicht wird eine Tasche nicht tun. 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.

+0

Wenn "9 1 2" eine akzeptable Antwort wäre, Sie don Wenn Sie erst einmal nach Bag drücken müssen, können Sie einfach die Schnittmenge der beiden Listen nehmen: "L (&) M" (mit der Texas-Version von ∩). Die Schnittmenge verwendet standardmäßig die Set-Semantik. –

+0

Taschen machen es perfekt für mich! Die Reihenfolge der Elemente, die von der Kreuzung zurückgegeben werden, spielt keine Rolle. – Anant

1

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; 

Ausgang:

[1 1 9 2] 
+2

Kinda Perl5ish suchen .. Sie könnten '@to_match X => 1;' verwenden, um den '% seen' Hash anstelle der Karte zu bauen, oder einfach auf den% seen Hash vollständig verzichten und' @some_numbers verwenden. grep: {@ to_match.first ($ _)}; ' –

+2

Funktioniert nicht richtig, wenn zusätzliche Elemente in der ersten Liste:' @some_numbers = 3, 1, 4, 1, 5, 9, 2, 6, 1; @to_match = 9, 7, 1, 2, 1' –

6

Sie können es mit Taschen:

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 .kxxv verwandeln.

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

Ausgang:

[9 1 1 2] 

(Wenn Sie sich nicht um Duplikate egal, Verwendung setzt anstelle von Taschen.)

+1

für alle, die Probleme mit Unicode-Operatoren haben, ist die Texas-Version von '∩' '(&)' – Christoph

Verwandte Themen