Próbuję wymyślić sposób sprawdzenia istnienia wartości w tablicy bez iteracji po tablicy.
Czytam plik dla parametru. Mam długą listę parametrów, z którymi nie chcę sobie poradzić. Te niechciane parametry umieściłem w tablicy @badparams
.
Chcę odczytać nowy parametr, a jeśli nie istnieje @badparams
, należy go przetworzyć. Jeśli istnieje @badparams
, przejdź do następnego czytania.
perl
arrays
comparison
Mel
źródło
źródło
Odpowiedzi:
Po prostu zamień tablicę w skrót:
Możesz również dodać więcej (unikalnych) parametrów do listy:
A później odzyskaj listę (unikalnych) parametrów:
źródło
1
ponownie.Najlepszy ogólny cel - szczególnie krótkie tablice (1000 elementów lub mniej) i kodery, które nie są pewne, jakie optymalizacje najlepiej odpowiadają ich potrzebom.
Wspomniano, że grep przechodzi przez wszystkie wartości, nawet jeśli pierwsza wartość w tablicy jest zgodna. To prawda, jednak grep jest nadal bardzo szybki w większości przypadków . Jeśli mówisz o krótkich tablicach (mniej niż 1000 pozycji), większość algorytmów i tak będzie dość szybka. Jeśli mówisz o bardzo długich tablicach (1 000 000 przedmiotów), grep jest akceptowalnie szybki, niezależnie od tego, czy element jest pierwszym, środkowym czy ostatnim w tablicy.
Przypadki optymalizacji dla dłuższych tablic:
Jeśli tablica jest posortowana , użyj „wyszukiwania binarnego”.
Jeśli ta sama tablica jest wielokrotnie przeszukiwana , najpierw skopiuj ją do skrótu, a następnie sprawdź skrót. Jeśli problemem jest pamięć, przenieś każdy element z tablicy do skrótu. Bardziej wydajna pamięć, ale niszczy oryginalną macierz.
Jeśli te same wartości są wielokrotnie wyszukiwane w tablicy, leniwie zbuduj pamięć podręczną. (podczas wyszukiwania każdego elementu najpierw sprawdź, czy wynik wyszukiwania został zapisany w utrwalonym haszu. jeśli wynik wyszukiwania nie zostanie znaleziony w haszu, następnie przeszukaj tablicę i umieść wynik w hasze utrwalonej, aby następnym razem znajdź go w haszu i pomiń wyszukiwanie).
Uwaga: te optymalizacje będą szybsze tylko w przypadku długich tablic. Nie przesadnie optymalizuj.
źródło
Możesz użyć funkcji SmartMatch w Perlu 5.10 w następujący sposób:
W przypadku wyszukiwania wartości dosłownej zrobienie tego załatwi sprawę.
W przypadku wyszukiwania skalarnego wykonywanie poniżej będzie działać jak powyżej.
W przypadku poniższej tablicy działającej, będzie działać jak powyżej.
W Perlu 5.18 smartmatch jest oznaczony jako eksperymentalny, dlatego musisz wyłączyć ostrzeżenia, włączając eksperymentalną pragmę, dodając poniżej do skryptu / modułu:
Alternatywnie, jeśli chcesz uniknąć korzystania z smartmatch - to, jak powiedział Aaron, użyj:
źródło
use experimental 'smartmatch'
jest zalecane. Ponieważ mam kontrolę nad moją wersją perla (system wewnętrzny), używamno warnings 'experimental::smartmatch';
instrukcji.Ten post na blogu omawia najlepsze odpowiedzi na to pytanie.
Krótko mówiąc, jeśli możesz zainstalować moduły CPAN, najbardziej czytelnymi rozwiązaniami są:
lub
Jednak bardziej powszechnym idiomem jest:
Ale proszę, nie używaj tej
first()
funkcji! W ogóle nie wyraża intencji twojego kodu. Nie używaj~~
operatora „Smart match”: jest zepsuty. I nie używajgrep()
ani rozwiązania z hashem: iterują całą listę.any()
przestanie, gdy tylko znajdzie wartość.Sprawdź post na blogu, aby uzyskać więcej informacji.
źródło
use List::Util qw(any);
.List::Util
jest w modułach Core .Metoda 1: grep (może zachować ostrożność, podczas gdy oczekuje się, że wartość będzie wyrażeniem regularnym).
Staraj się unikać używania
grep
, jeśli patrzysz na zasoby.Metoda 2: Wyszukiwanie liniowe
Metoda 3: Użyj skrótu
Metoda 4: SmartMatch
(dodano w Perlu 5.10, zaznaczono eksperymentalnie w Perlu 5.18).
Metoda 5: Użyj modułu
List::MoreUtils
źródło
Benchmark @ eakssjo jest zepsuty - miary tworzące pętle w porównaniu do tworzenia wyrażeń regularnych w pętli. Naprawiona wersja (plus dodałem
List::Util::first
iList::MoreUtils::any
):I wynik (dotyczy iteracji 100_000, dziesięć razy więcej niż w odpowiedzi @ eakssjo):
źródło
Mimo że jest wygodny w użyciu, wygląda na to, że konwersja na hash kosztuje sporo wydajności, co było dla mnie problemem.
Wynik testu porównawczego:
źródło
List::Util::first
jest szybsze, ponieważ przestaje iterować po znalezieniu dopasowania.grep
jest znacznie wolniejszy niż tworzenie skrótu i wyszukiwanie, ponieważ pierwszy to O (n), a drugi O (1). Po prostu wykonaj tworzenie skrótu tylko raz (poza pętlą) i oblicz wyrażenie regularne tylko w celu zmierzenia metod ( zobacz moją odpowiedź ).@plik to istniejąca tablica
/^2[\d].[\d][A-za-z]?/ = vaues począwszy od 2 tutaj możesz umieścić dowolne wyrażenie regularne
źródło
Na pewno chcesz tutaj hash. Umieść złe parametry jako klucze w haszu, a następnie zdecyduj, czy dany parametr istnieje w haszu.
Jeśli naprawdę chcesz to zrobić za pomocą tablicy, spójrz na
List::Util
lubList::MoreUtils
źródło
Można to zrobić na dwa sposoby. Możesz użyć wrzucania wartości do skrótu dla tabeli odnośników, jak sugerują inne posty. (Dodam tylko kolejny idiom.)
Ale jeśli są to dane składające się głównie z znaków słownych i niezbyt dużej liczby meta, możesz zrzucić je na zmianę wyrażenia regularnego:
To rozwiązanie musiałoby zostać dostosowane do typów „złych wartości”, których szukasz. I znowu, może to być całkowicie niewłaściwe dla niektórych rodzajów ciągów, więc zastrzegaj emptor .
źródło
@bad_param_lookup{@bad_params} = ()
, ale musisz użyćexists
do przetestowania członkostwa.Możesz sprawdzić spójność liczbową spacji wiodących
źródło