Jaka jest dokładnie różnica między array_map
, array_walk
a array_filter
. Z dokumentacji wynika, że można przekazać funkcję wywołania zwrotnego, aby wykonać akcję na dostarczonej tablicy. Ale wydaje mi się, że nie znajduję między nimi żadnej szczególnej różnicy.
Czy wykonują to samo?
Czy można ich używać zamiennie?
Byłbym wdzięczny za twoją pomoc z przykładowym przykładem, jeśli w ogóle są one różne.
Odpowiedzi:
array_map
nie może zmieniać wartości w tablicach wejściowych, aarray_walk
może; w szczególnościarray_map
nigdy nie zmienia swoich argumentów.array_map
nie może działać z kluczami macierzy,array_walk
może.array_map
zwraca nową tablicę,array_walk
tylko zwracatrue
. Dlatego też, jeśli nie chcesz, aby utworzyć tablicę w wyniku przechodzenia jednej tablicy, należy użyćarray_walk
.array_map
może również odbierać dowolną liczbę tablic i może iterować je równolegle, podczas gdyarray_walk
działa tylko na jednej.array_walk
może otrzymać dodatkowy dowolny parametr, aby przekazać go do wywołania zwrotnego. Jest to w większości nieistotne od PHP 5.3 (kiedy wprowadzono anonimowe funkcje ).array_map
ma taką samą długość jak największa tablica wejściowa;array_walk
nie zwraca tablicy, ale jednocześnie nie może zmienić liczby elementów oryginalnej tablicy;array_filter
wybiera tylko podzbiór elementów tablicy zgodnie z funkcją filtrowania. Zachowuje klucze.Przykład:
Wynik:
źródło
array_map(callback($key, $value), array_keys($array), $array)
Pomysł mapowania funkcji na tablicę danych pochodzi z programowania funkcjonalnego. Nie powinieneś myśleć o tym
array_map
jako oforeach
pętli, która wywołuje funkcję na każdym elemencie tablicy (nawet jeśli tak jest zaimplementowana). Należy pomyśleć o zastosowaniu tej funkcji do każdego elementu w tablicy niezależnie.Teoretycznie takie rzeczy jak mapowanie funkcji można wykonywać równolegle, ponieważ funkcja zastosowana do danych powinna TYLKO wpływać na dane, a NIE na stan globalny. Wynika to z faktu, że a
array_map
może wybrać dowolną kolejność zastosowania funkcji do elementów w (nawet jeśli w PHP tak nie jest).array_walk
z drugiej strony jest to dokładnie odwrotne podejście do obsługi tablic danych. Zamiast obsługiwać każdy element osobno, używa on state (&$userdata
) i może edytować element w miejscu (podobnie jak w pętli foreach). Ponieważ za każdym razem, gdy element zostanie$funcname
zastosowany, może on zmienić globalny stan programu i dlatego wymaga jednego poprawnego sposobu przetwarzania elementów.Z powrotem w krainie PHP
array_map
iarray_walk
są prawie identyczne, z wyjątkiem tego,array_walk
że dają większą kontrolę nad iteracją danych i zwykle są używane do „zmiany” danych w miejscu w porównaniu do zwracania nowej „zmienionej” tablicy.array_filter
jest tak naprawdę aplikacjąarray_walk
(lubarray_reduce
) i mniej więcej zapewnia wygodę.źródło
array_filter()
można go zaimplementowaćarray_walk()
?Z dokumentacji
array_walk bierze tablicę i funkcję
F
i modyfikuje ją, zastępując każdy element xF(x)
.array_map robi dokładnie to samo, z tą różnicą, że zamiast modyfikować w miejscu, zwraca nową tablicę z transformowanymi elementami.
array_filter z funkcją
F
, zamiast przekształcać elementy, usunie wszystkie elementy, dla którychF(x)
nie jest to prawdąźródło
array_walk
zwrócił tablicę podobną do tejarray_map
i zorientowałem się, że problem leży w mojej funkcji. Nie zdawałem sobie sprawy, dopóki nie zobaczyłem, że typ zwracany jest wartością logiczną.Pozostałe odpowiedzi dość dobrze pokazują różnicę między array_walk (modyfikacja lokalna) a array_map (zwracana zmodyfikowana kopia). Jednak tak naprawdę nie wspominają o array_reduce, co jest świetnym sposobem na zrozumienie array_map i array_filter.
Funkcja array_reduce pobiera tablicę, funkcję dwóch argumentów i „akumulator”, takie jak to:
Elementy tablicy są łączone z akumulatorem pojedynczo, przy użyciu podanej funkcji. Wynik powyższego wywołania jest taki sam, jak w przypadku:
Jeśli wolisz myśleć w kategoriach pętli, to jest jak wykonanie następujących czynności (faktycznie wykorzystałem to jako awarię, gdy funkcja array_reduce nie była dostępna):
Ta wersja z zapętleniem wyjaśnia, dlaczego nazwałem trzeci argument „akumulatorem”: możemy go używać do gromadzenia wyników podczas każdej iteracji.
Co to ma wspólnego z array_map i array_filter? Okazuje się, że oba są szczególnym rodzajem zmniejszania tablicy. Możemy zaimplementować je w następujący sposób:
Zignoruj fakt, że array_map i array_filter przyjmują argumenty w innej kolejności; to tylko kolejne dziwactwo PHP. Ważne jest to, że prawa strona jest identyczna, z wyjątkiem funkcji, które nazwałem $ MAP i $ FILTER. Jak więc wyglądają?
Jak widać, obie funkcje pobierają akumulator $ i zwracają go ponownie. Istnieją dwie różnice w tych funkcjach:
Zauważ, że jest to dalekie od bezużytecznych ciekawostek; możemy go użyć do zwiększenia wydajności naszych algorytmów!
Często możemy zobaczyć kod podobny do tych dwóch przykładów:
Użycie array_map i array_filter zamiast pętli sprawia, że te przykłady wyglądają całkiem ładnie. Jednak może być bardzo nieefektywne, jeśli $ input jest duży, ponieważ pierwsze wywołanie (mapa lub filtr) przejdzie $ $ i zbuduje tablicę pośrednią. Ta tablica pośrednia jest przekazywana bezpośrednio do drugiego wywołania, które ponownie przejdzie całą sprawę, a następnie tablica pośrednia będzie musiała zostać wyrzucona.
Możemy pozbyć się tej pośredniej tablicy, wykorzystując fakt, że zarówno array_map, jak i array_filter są przykładami zmniejszenia tablicy. Łącząc je, musimy przejrzeć $ $ tylko raz w każdym przykładzie:
UWAGA: Moje implementacje array_map i array_filter powyżej nie będą zachowywać się dokładnie tak, jak PHP, ponieważ moja array_map może obsługiwać tylko jedną tablicę na raz, a mój array_filter nie użyje „pustego” jako domyślnej funkcji $. Ponadto żaden nie zachowa kluczy.
Nie jest trudno sprawić, by zachowywały się jak PHP, ale czułem, że te komplikacje utrudnią dostrzeżenie podstawowej idei.
źródło
Poniższa wersja ma na celu wyraźniejsze określenie PHP array_filer (), array_map () i array_walk (), z których wszystkie pochodzą z programowania funkcjonalnego:
array_filter () odfiltrowuje dane, w wyniku czego nowa tablica zawiera tylko pożądane elementy poprzedniej tablicy, w następujący sposób:
kod na żywo tutaj
Wszystkie wartości liczbowe są odfiltrowywane z tablicy $, pozostawiając $ filtrowane tylko z rodzajami owoców.
array_map () tworzy również nową tablicę, ale w przeciwieństwie do array_filter () tablica wynikowa zawiera każdy element wejściowego $ filtrowanego, ale ze zmienionymi wartościami, dzięki zastosowaniu wywołania zwrotnego do każdego elementu, jak następuje:
kod na żywo tutaj
W tym przypadku kod stosuje wywołanie zwrotne za pomocą wbudowanej funkcji strtoupper (), ale funkcja zdefiniowana przez użytkownika jest również inną wykonalną opcją. Wywołanie zwrotne ma zastosowanie do każdego elementu $ filtrowanego, a zatem wywołuje $ nu, którego elementy zawierają wielkie litery.
W następnym fragmencie tablica walk () przechodzi przez $ nu i wprowadza zmiany w każdym elemencie względem operatora odniesienia „&”. Zmiany następują bez tworzenia dodatkowej tablicy. Wartość każdego elementu zamienia się w bardziej informacyjny ciąg określający jego klucz, kategorię i wartość.
Zobacz demo
Uwaga: funkcja zwrotna w odniesieniu do array_walk () przyjmuje dwa parametry, które automatycznie uzyskują wartość elementu i jego klucza oraz w tej kolejności, również w przypadku wywołania przez array_walk (). (Zobacz więcej tutaj ).
źródło
$lambda
i$callback
są tylko rozszerzeniem istniejących funkcji, a zatem są całkowicie zbędne. Możesz uzyskać ten sam wynik, przekazując (nazwę) podstawową funkcję:$filtered = array_filter($array, 'ctype_alpha');
i$nu = array_map('strtoupper', $filtered);