Czy istnieje sposób na zrobienie czegoś takiego:
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
var_dump(array_map(function($a, $b) { return "$a loves $b"; },
array_keys($test_array),
array_values($test_array)));
Ale zamiast wywoływać array_keys
i array_values
bezpośrednio przekazywać $test_array
zmienną?
Pożądane wyjście to:
array(2) {
[0]=>
string(27) "first_key loves first_value"
[1]=>
string(29) "second_key loves second_value"
}
php
functional-programming
José Tomás Tocino
źródło
źródło
Odpowiedzi:
Nie z array_map, ponieważ nie obsługuje kluczy.
array_walk robi:
Zmienia jednak tablicę podaną jako parametr, więc nie jest to do końca funkcjonalne programowanie (ponieważ masz tak oznaczone pytanie). Ponadto, jak wskazano w komentarzu, spowoduje to jedynie zmianę wartości tablicy, więc klucze nie będą zgodne z danymi podanymi w pytaniu.
Jeśli chcesz, możesz napisać funkcję, która naprawia punkty powyżej.
źródło
$a = "$b loves $a"
dopasować pożądane wyjście OP.array_walk()
nie zwraca wynikowej tablicy, ale bool.Jest to prawdopodobnie najkrótszy i najłatwiejszy do uzasadnienia temat:
źródło
array_keys()
. Wydaje się to jednak głupim wymogiem.Oto moje bardzo proste rozwiązanie kompatybilne z PHP 5.5:
Podane przez Ciebie wywołanie powinno zwrócić tablicę z dwiema wartościami, tj
return [key, value]
. Wewnętrzne wezwanie doarray_map
tworzy zatem tablicę tablic. To następnie jest konwertowane z powrotem do tablicy jednowymiarowej przezarray_column
.Stosowanie
Wynik
Częściowe zastosowanie
W przypadku, gdy trzeba używać tej funkcji wiele razy z różnymi tablicami, ale z tą samą funkcją mapowania, można zrobić coś, co nazywa się aplikacją funkcji częściowej (związaną z „ curry ”), co pozwala na przekazanie tablicy danych tylko po wywołaniu:
Który daje taką samą wydajność, podaną
$func
i$ordinals
są jak wcześniej.UWAGA: jeśli funkcja zamapowana zwraca ten sam klucz dla dwóch różnych danych wejściowych, wartość powiązana z późniejszym kluczem wygra. Odwróć tablicę wejściową i wynik wyjściowy,
array_map_assoc
aby umożliwić wygrywanie wcześniejszym kluczom. (Zwrócone klucze w moim przykładzie nie mogą kolidować, ponieważ zawierają klucz tablicy źródłowej, która z kolei musi być unikalna).Alternatywny
Poniżej przedstawiono wariant powyższego, który dla niektórych może okazać się bardziej logiczny, ale wymaga PHP 5.6:
W tym wariancie podana funkcja (na której odwzorowana jest tablica danych) powinna zamiast tego zwrócić tablicę asocjacyjną z jednym wierszem, tj
return [key => value]
. Wynik mapowania wywoływanego elementu jest następnie po prostu rozpakowywany i przekazywany doarray_merge
. Tak jak wcześniej, zwrócenie duplikatu klucza spowoduje wygraną późniejszych wartości.Jeśli korzystasz z PHP 5.3 do 5.5, poniższe są równoważne. Wykorzystuje
array_reduce
i+
operator tablicy binarnej do konwersji wynikowej tablicy dwuwymiarowej na tablicę jednowymiarową przy jednoczesnym zachowaniu kluczy:Stosowanie
Oba te warianty zostałyby wykorzystane w ten sposób:
Uwaga
=>
zamiast,
w$func
.Dane wyjściowe są takie same jak poprzednio i każdy może być częściowo zastosowany w taki sam sposób jak poprzednio.
Podsumowanie
Pierwotne pytanie ma na celu uproszczenie wywołania wywołania kosztem posiadania bardziej skomplikowanej funkcji, która zostanie wywołana; szczególnie, aby mieć możliwość przekazania tablicy danych jako jednego argumentu, bez dzielenia kluczy i wartości. Korzystanie z funkcji dostarczonej na początku tej odpowiedzi:
Lub, tylko dla tego pytania, możemy uprościć
array_map_assoc()
funkcję, która upuszcza klucze wyjściowe, ponieważ pytanie nie wymaga ich:Tak więc odpowiedź brzmi NIE , nie można uniknąć dzwonienia
array_keys
, ale można wykreślić miejsce, w którymarray_keys
wywoływana jest funkcja wyższego rzędu, co może być wystarczająco dobre.źródło
array_merge
przez,array_replace
aby zachować klucze, które byłyby liczbami całkowitymi.W wersji PHP 5.3 lub nowszej:
źródło
Tak zaimplementowałem to w moim projekcie.
źródło
Popatrz tutaj! Istnieje trywialne rozwiązanie!
Jak stwierdzono w pytaniu,
array_map
ma już dokładnie wymaganą funkcjonalność . Inne odpowiedzi tutaj poważnie komplikują:array_walk
nie działa.Stosowanie
Dokładnie tak, jak można oczekiwać po swoim przykładzie:
źródło
qrrqy_keys()
nie powinno być używane przez #reasonsPrzez „ręczną pętlę” miałem na myśli napisanie niestandardowej funkcji, która używa
foreach
. Zwraca to nową tablicę, podobnie jakarray_map
robi, ponieważ zasięg funkcji powoduje,$array
że jest to kopia, a nie odwołanie:Twoja technika używania
array_map
zarray_keys
chociaż wydaje się być prostsza i bardziej wydajna, ponieważ możesz użyćnull
jako wywołania zwrotnego, aby zwrócić pary klucz-wartość:źródło
unset( $value )
ponieważ wciąż istnieje w zdefiniowanym zakresie.W oparciu o odpowiedź eis , oto co ostatecznie zrobiłem, aby uniknąć bałaganu w oryginalnej tablicy:
źródło
array_walk
ponieważ nie odwołujesz się do niego w zamknięciu.Zrobiłem tę funkcję na podstawie odpowiedzi eis :
Przykład:
Wynik:
Oczywiście możesz użyć,
array_values
aby zwrócić dokładnie to, czego chce OP.źródło
$arr
typu tablica typów, jednak jeśli wpiszesz podpowiedzi jakocallable
iarray
możesz zamiast tego upuścić czek dois_callable
. Następnie tworzysz przypisanie do wartości $, która jest następnie nieużywana. Powinieneś po prostu zignorować wartość zwracaną. Po trzecie, lepiej byłoby zgłosić wyjątek w wywołaniu zwrotnym niż zwrócić wartość false. Wówczas albo zawsze zwracałby prawidłową wartość, albo zawsze rzucał.Biblioteka YaLinqo * dobrze nadaje się do tego rodzaju zadań. Jest to port LINQ z .NET, który w pełni obsługuje wartości i klucze we wszystkich wywołaniach zwrotnych i przypomina SQL. Na przykład:
Lub tylko:
Oto
'"$k loves $v"'
skrót do składni pełnego zamknięcia obsługiwanej przez tę bibliotekę.toArray()
w końcu jest opcjonalny. Łańcuch metod zwraca iterator, więc jeśli wynik wymaga tylko iteracji za pomocąforeach
,toArray
wywołanie można usunąć.* opracowane przeze mnie
źródło
Zrobiłbym coś takiego:
Wyniki:
źródło
Dodam jeszcze jedno rozwiązanie problemu przy użyciu wersji 5.6 lub nowszej. Nie wiem, czy jest bardziej wydajny niż i tak już świetne rozwiązania (prawdopodobnie nie), ale dla mnie jest po prostu łatwiej czytać:
Używając
strval()
jako przykładowej funkcji warray_map
, wygeneruje:Mam nadzieję, że nie tylko ja uważam to za dość proste.
array_combine
tworzykey => value
tablicę z tablicy kluczy i tablicy wartości, reszta jest dość oczywista.źródło
Możesz użyć metody mapowania z tej biblioteki tablic, aby osiągnąć dokładnie to, czego chcesz tak łatwo, jak:
zachowuje również klucze i zwraca nową tablicę, nie wspominając o kilku różnych trybach, które pasują do twoich potrzeb.
źródło
Źródło
źródło
Zawsze lubię javascriptowy wariant mapy tablic. Najprostsza wersja to:
Teraz możesz przekazać funkcję wywołania zwrotnego, jak skonstruować wartości.
źródło
h(g(f($data)))
zastosowanief
, a następnieg
, po czymh
do listy dane. Generalnie uważa się za bardziej uniwersalne w programowaniu funkcjonalnym posiadanie funkcji, która wykonuje tę samą operację na danych nurków, niż funkcja, która stosuje funkcje nurków do ustalonego zestawu danych.Inny sposób na zrobienie tego z (poza) zachowaniem kluczy:
źródło
Widzę, że brakuje oczywistej odpowiedzi:
Działa dokładnie tak, jak array_map. Prawie.
W rzeczywistości nie jest tak czysty,
map
jak znasz go z innych języków. Php jest bardzo dziwny, dlatego wymaga bardzo dziwnych funkcji użytkownika, ponieważ nie chcemy zerwać z naszym dokładnie zepsutymworse is better
podejściem.Naprawdę wcale tak nie jest
map
. Jednak nadal jest bardzo przydatny.Pierwszą oczywistą różnicą od array_map jest to, że callback pobiera dane wyjściowe
each()
z każdej tablicy wejściowej zamiast samej wartości. Nadal możesz iterować więcej tablic jednocześnie.Druga różnica polega na sposobie obsługi klucza po jego zwróceniu z wywołania zwrotnego; wartość zwracana z funkcji zwrotnej powinna wynosić
array('new_key', 'new_value')
. Klucze można i będą zmieniane, te same klucze mogą nawet spowodować zastąpienie poprzedniej wartości, jeśli ten sam klucz został zwrócony. To nie jest powszechnemap
zachowanie, ale pozwala przepisać klucze.Trzecią dziwną rzeczą jest to, że jeśli pominiesz
key
wartość zwracaną (przezarray(1 => 'value')
lubarray(null, 'value')
), zostanie przypisany nowy klucz, tak jakby$array[] = $value
został użyty. To też niemap
jest powszechne zachowanie, ale wydaje mi się, że czasem przydaje się.Czwarta dziwna rzecz: jeśli funkcja zwrotna nie zwraca wartości lub zwraca
null
, cały zestaw bieżących kluczy i wartości jest pomijany na wyjściu, jest po prostu pomijany. Ta funkcja jest całkowiciemap
niedostępna, ale sprawiłaby, że ta funkcja byłaby doskonała dla kaskaderówarray_filter_assoc
, gdyby była taka funkcja.Jeśli pominiesz drugi element (
1 => ...
) ( część wartości ) w zwrocie wywołania zwrotnego,null
zostanie użyty zamiast wartości rzeczywistej.Wszelkie inne elementy oprócz tych z kluczami
0
i1
po oddzwonieniu są ignorowane.I na koniec, jeśli lambda zwraca dowolną wartość oprócz
null
lub tablicę, jest to traktowane tak, jakby pominięto zarówno klucz, jak i wartość, więc:null
jest używany jako jego wartośćUWAGA:
W przeciwieństwie do in
array_map
, wszystkie parametry niebędącearray_map_assoc
macierzami, z wyjątkiem pierwszego parametru wywołania zwrotnego, są dyskretnie rzutowane na tablice.PRZYKŁADY:
// TODO: examples, anyone?
źródło