2010-12-31 8 views
11

Jeśli mam tablicę:Perl: Dobry sposób na sprawdzenie, czy wartość znajduje się w tablicy?

@int_array = (7,101,80,22,42); 

Jak mogę sprawdzić, czy wartość całkowita 80 jest w tablicy bez zapętlenie poprzez każdego elementu?

+0

Wygląda na duplikat: http://stackoverflow.com/questions/2860226 – Calimo

+0

Możliwy duplikat [Jak mogę sprawdzić, czy tablica Perla zawiera konkretną wartość?] (Http://stackoverflow.com/questions/2860226/how-can-i-check-if-a-perl-array-zawiera-a-value-value) – ThisSuitIsBlackNot

Odpowiedz

29

Nie można bez pętli. To część tego, co znaczy być tablicą. Możesz użyć niejawnej pętli, używając grep lub smartmatch, ale nadal istnieje pętla. Jeśli chcesz uniknąć pętli, użyj zamiast tego skrótu (lub dodatkowo).

# grep 
if (grep $_ == 80, @int_array) ... 

# smartmatch 
use 5.010001; 
if (80 ~~ @int_array) ... 

Przed użyciem smartmatch, uwaga:

http://search.cpan.org/dist/perl-5.18.0/pod/perldelta.pod#The_smartmatch_family_of_features_are_now_experimental:

smartmatch rodzina funkcje są teraz eksperymentalny

Inteligentne mecz, dodane w v5.10.0 i znacznie poprawione w wersji 5.10.1 był stałym punktem skargi. Chociaż jest wiele sposobów, w jakie jest przydatny, okazało się również problematyczne i mylące zarówno dla użytkowników, jak i implementatorów Perla. Pojawiło się wiele propozycji, jak najlepiej rozwiązać problem. Jest oczywiste, że smartmatch prawie na pewno albo zmieni się, albo odejdzie w przyszłości. Poleganie na jego bieżącym zachowaniu nie jest zalecane.

Ostrzeżenia będą teraz wyświetlane, gdy analizator składni zobaczy ~~, given lub when. Aby wyłączyć te ostrzeżenia, można dodać tę linię do odpowiedniego zakresu

+0

++. Inteligentne dopasowanie (a może coś z Listy :: MoreUtils) jest drogą do zrobienia. Aby uzyskać kompletność, oto jak można to zrobić za pomocą skrótu: my @array = 1..1000; mój% hash; undef @hash {@array}; powiedz "10 jest w tablicy!" jeśli istnieje $ hash {10}; – Hugmeir

+2

'undef @hash {@array}' działa, ale tak naprawdę nie jest tak udokumentowane. zamiast tego użyj '@hash {@array} =()'. – ysth

+0

Nie byłem pewien, co miałeś na myśli, więc wybrałem go i znalazłem to: http://www.perlmonks.org/?node_id=435223 Dzięki za poprawkę, tak! – Hugmeir

0
if (grep /^80$/, @int_array) { 
    ... 
} 
+0

Pasuje również do 180 i 800. – aschepler

+0

Dodano kotwice .. –

+0

Używanie grep ogólnie nie jest dobrym pomysłem ; przydzieli dodatkową listę, aby zatrzymać wyniki grepa, i będzie kontynuował przeglądanie tablicy, nawet jeśli pierwszy element to 80. –

0

Jeśli używasz Perl 5.10 lub nowszy, można użyć operatora smart match~~: rozwiązanie

my $found = (80 ~~ $in_array); 
7

CPAN: używać List::MoreUtils

use List::MoreUtils qw{any}; 
print "found!\n" if any { $_ == 7 } (7,101,80,22,42); 

Jeśli potrzebujesz wykonać WIELU WIELKICH wyszukiwań w tej samej tablicy, bardziej wydajnym sposobem jest zapisanie tablicy w haszowaniu i wyszukanie w haśle :

@int_array{@int_array} = 1; 
foreach my $lookup_value (@lookup_values) { 
    print "found $lookup_value\n" if exists $int_array{$lookup_value} 
} 

Dlaczego warto używać tego rozwiązania zamiast alternatywy?

  • Nie można użyć inteligentnego dopasowania w Perlu przed 5.10. Zgodnie z tym postem SO Briana d foya] 2, inteligentne dopasowanie jest zwarciem, więc jest tak dobre jak "dowolne" rozwiązanie dla 5.10.

  • grep rozwiązanie pętle listę cały nawet jeśli pierwszy element 1,000,000 długiej listy meczów. any spowoduje zwarcie i zakończy działanie w momencie znalezienia pierwszego dopasowania, dzięki czemu jest bardziej wydajne. Oryginalny plakat wyraźnie powiedział "bez zapętlenia się przez każdy element".

  • Jeśli chcesz wykonać wiele wyszukiwań, jednorazowy koszt utraconego tworzenia skrótu sprawia, że ​​metoda porównywania hash jest o wiele wydajniejsza niż jakakolwiek inna.Zobacz this SO post for details

+0

Cóż, zależy to od wielkości tablicy i liczby kontroli, które należy wykonać. Parsowanie modułu zewnętrznego może być mniej wydajne niż pełne 'grep'. –

+0

Również jeśli wydajność jest głównym problemem, po prostu wykonaj instrukcję 'foreach' z' last'. –

+2

@kemp - IIRC, List :: MoreUtils ma implementację XS. To jest szybciej niż foreach z ostatnim. jeśli używasz natywnego Perla, prawdopodobnie to właśnie robi moduł. – DVK

3

Jeszcze innym sposobem, aby sprawdzić numer w tablicy:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use List::Util 'first'; 

my @int_array  = qw(7 101 80 22 42); 
my $number_to_check = 80; 

if (first { $_ == $number_to_check } @int_array) { 
    print "$number_to_check exists in ", join ', ', @int_array; 
} 

zobaczyć List::Util.

Powiązane problemy