2017-01-20 22 views
6

Załóżmy, że mam dużą tablicę, @stuff i $thing, i chcę wiedzieć, czy $thing jest w @stuff. Jaki jest najlepszy sposób na zrobienie tego w Perlu 6? I z "najlepszym" mam na myśli: idiomatyczny, czytelny, wydajny; niekoniecznie w tej kolejności.Perl 6: jaki jest najlepszy sposób sprawdzenia, czy element znajduje się na liście?

W rzeczywistości istnieją dwa oddzielne przypadki. Jednym z nich jest to, że musisz wykonać wiele testów dla różnych $thing s, a drugi jest tam, gdzie robisz to tylko raz lub kilka razy.

Najpierw przyjrzyjmy się pierwszemu przypadkowi. Myślę, że znam (lub) właściwą odpowiedź.

my $set-of-stuff = set @stuff; 
for @whatever -> $thing { 
    do-something-with($thing) if $thing ∈ $set of stuff; 
} 

Rzeczywiście można pominąć pierwszą linię i po prostu powiedzieć ... if $thing ∈ @stuff, ale prawie na pewno mają dużo gorsze wyniki, ponieważ zestaw jest tworzony za każdym razem.

Ale teraz drugi przypadek, mam tylko jeden $thing do sprawdzenia. Powyższe rozwiązanie działa, oczywiście, ale utworzenie zestawu, aby go raz sprawdzić, wydaje się dużo narzutem. Skrót

do-something-with($thing) if $thing ∈ @stuff; 

sprawia trochę więcej sensu tutaj, ponieważ mamy tylko nazywają go raz. Ale wciąż musimy stworzyć zestaw do jednego użytku.

Nieco bardziej tradycyjny jest:

do-something-with($thing) if @stuff.grep($thing); 

lub potencjalnie szybciej:

do-something-with($thing) if @stuff.first($thing); 

Ale to wydaje się mniej idiomatyczne, a na pewno drugi jest mniej czytelny niż $thing ∈ @stuff.

Nie sądzę, że istnieje rozwiązanie do inteligentnego dopasowania, prawda? Z pewnością to nie działa:

do-something-with($thing) if $thing ~~ @stuff; 

Jakieś przemyślenia?

Odpowiedz

11

Zależy od definicji "najlepszego" lub "inteligentnego".

Jeśli mówimy o wydajności, jestem całkiem pewny

@stuff.first($thing) 

jest najszybszy.

Idiomatically, w pobliżu powyżej rozwiązania to:

$thing ~~ any @stuff 

, która ma potencjał o lepszej wydajności wallclock skutek automatycznego gwintu.

Użycie do tego celu zestawów sprawia, że ​​kod wygląda bliżej logiki formalnej. Ale nie przyspieszy to działania, ponieważ zestaw musi zostać utworzony (chyba, że ​​może być stworzony podczas kompilacji).

Nie wiem, czy istnieje "najlepsza" odpowiedź na tę.

+0

Dzięki, powinienem był pomyśleć o "dowolnym".Jednak z mojego doświadczenia wynika, że ​​połączenia w obecnych wersjach Rakudo są bardzo powolne, więc prawdopodobnie nie jest to dobra opcja (jeszcze). – mscha

+0

Co jest "najlepsze"? Cóż, to chyba zależy od sytuacji. Idealnie, najlepsza wydajność, idiomatyczność (sic?) I czytelność, ale w praktyce trzeba iść na kompromis. Możesz poświęcić trochę wydajności dla czytelności, na przykład, ale nie za dużo. – mscha

+0

W rzeczywistości '[email protected] ($ thing)' powinno być równie szybkie jak '@ stuff.first ($ thing)' (ponieważ zatrzymuje się po znalezieniu czegoś, co pasuje) –

Powiązane problemy