Kod:
function search($array, $key, $value)
{
$results = array();
if (is_array($array)) {
if (isset($array[$key]) && $array[$key] == $value) {
$results[] = $array;
}
foreach ($array as $subarray) {
$results = array_merge($results, search($subarray, $key, $value));
}
}
return $results;
}
$arr = array(0 => array(id=>1,name=>"cat 1"),
1 => array(id=>2,name=>"cat 2"),
2 => array(id=>3,name=>"cat 1"));
print_r(search($arr, 'name', 'cat 1'));
Wynik:
Array
(
[0] => Array
(
[id] => 1
[name] => cat 1
)
[1] => Array
(
[id] => 3
[name] => cat 1
)
)
Jeśli wydajność jest ważna, możesz ją zapisać, aby wszystkie wywołania rekurencyjne zapisywały swoje wyniki w tej samej tymczasowej $results
tablicy zamiast scalać tablice razem, na przykład:
function search($array, $key, $value)
{
$results = array();
search_r($array, $key, $value, $results);
return $results;
}
function search_r($array, $key, $value, &$results)
{
if (!is_array($array)) {
return;
}
if (isset($array[$key]) && $array[$key] == $value) {
$results[] = $array;
}
foreach ($array as $subarray) {
search_r($subarray, $key, $value, $results);
}
}
Kluczem jest to, że search_r
czwarty parametr przyjmuje jako odniesienie, a nie wartość; znak ampersand &
ma kluczowe znaczenie.
FYI: Jeśli masz starszą wersję PHP następnie trzeba określić udział pass-by-reference na wezwanie do search_r
aniżeli w swojej deklaracji. Oznacza to, że ostatnia linia staje się search_r($subarray, $key, $value, &$results)
.
$key
nie istnieje w tablicy? Czy nie byłoby lepiejif (array_key_exists($key, $array) && $array[$key] == $value) {
?$value
które jest,null
a funkcja nie działa ...array empty
... Jak mieć tablicę, nawet jeśli$value
=null
? jaksearch($array, 'id', null)
?A może zamiast tego wersja SPL ? Zaoszczędzi ci to pisania:
Wspaniałe jest to, że w zasadzie ten sam kod będzie iterował przez katalog za Ciebie, używając RecursiveDirectoryIterator zamiast RecursiveArrayIterator. SPL jest roxorem.
Jedynym minusem SPL jest to, że jest źle udokumentowany w sieci. Jednak kilka książek poświęconych PHP zawiera przydatne szczegóły, szczególnie Pro PHP; i prawdopodobnie możesz też wygooglować więcej informacji.
źródło
Ref: http://php.net/manual/en/function.array-filter.php
źródło
Wróciłem, aby opublikować tę aktualizację dla każdego, kto potrzebuje porady dotyczącej optymalizacji tych odpowiedzi, w szczególności świetnej odpowiedzi Johna Kugelmana powyżej.
Jego opublikowana funkcja działa dobrze, ale musiałem zoptymalizować ten scenariusz do obsługi zestawu wyników 12 000 wierszy. Funkcja ta potrzebowała wiecznych 8 sekund na przejrzenie wszystkich rekordów, ale za długo.
Po prostu potrzebowałem funkcji STOP wyszukiwania i powrotu po znalezieniu dopasowania. To znaczy, jeśli szukasz customer_id, wiemy, że mamy tylko jeden w zbiorze wyników i po znalezieniu customer_id w tablicy wielowymiarowej, chcemy zwrócić.
Oto zoptymalizowana pod kątem szybkości (i znacznie uproszczona) wersja tej funkcji dla każdego, kto jej potrzebuje. W przeciwieństwie do innych wersji, obsługuje tylko jedną głębokość tablicy, nie powtarza się i eliminuje scalanie wielu wyników.
Spowodowało to skrócenie czasu zadania dopasowania 12 000 rekordów do 1,5 sekundy. Wciąż bardzo kosztowne, ale znacznie bardziej rozsądne.
źródło
Drobne poprawki do szybkiej wersji.
źródło
Uważaj na algorytmy wyszukiwania liniowego (powyższe są liniowe) w tablicach wielowymiarowych, ponieważ mają złożoną złożoność, ponieważ jej głębokość zwiększa liczbę iteracji wymaganych do przejścia całej tablicy. Na przykład:
zajęłoby co najwyżej 200 iteracji, aby znaleźć to, czego szukasz (gdyby igła miała wartość [100] [1]), przy użyciu odpowiedniego algorytmu.
Algorytmy liniowe w tym przypadku działają w O (n) (uporządkuj całkowitą liczbę elementów w całej tablicy), jest to słabe, milion wpisów (np. Tablica 1000x100x10) wymagałoby średnio 500 000 iteracji, aby znaleźć igłę. Co by się stało, gdybyś zdecydował się zmienić strukturę swojej wielowymiarowej tablicy? A PHP wykopałby algorytm rekurencyjny, gdyby twoja głębokość była większa niż 100. Informatyka może zrobić lepiej:
Tam, gdzie to możliwe, zawsze używaj obiektów zamiast tablic wielowymiarowych:
i zastosuj niestandardowy interfejs i funkcję komparatora, aby je posortować i znaleźć:
Możesz użyć
uasort()
niestandardowego komparatora, jeśli masz ochotę na przygodę, powinieneś zaimplementować własne kolekcje dla swoich obiektów, które mogą je sortować i zarządzać nimi (zawsze rozszerzam ArrayObject, aby zawierał przynajmniej funkcję wyszukiwania).Po posortowaniu (uasort to O (n log n), co jest tak dobre, jak w przypadku dowolnych danych), wyszukiwanie binarne może wykonać operację w czasie O (log n), tj. Milion wpisów zajmuje tylko ~ 20 iteracji Szukaj. O ile wiem, wyszukiwanie binarne niestandardowego komparatora nie jest zaimplementowane w PHP (
array_search()
używa naturalnego porządku, który działa na odwołaniach do obiektów, a nie na ich właściwościach), musiałbyś to zaimplementować samodzielnie, tak jak ja.To podejście jest bardziej wydajne (nie ma już głębi) i, co ważniejsze, uniwersalne (zakładając, że wymuszasz porównywalność za pomocą interfejsów), ponieważ obiekty definiują sposób ich sortowania, dzięki czemu można nieskończenie powtarzać kod. Znacznie lepiej =)
źródło
Oto rozwiązanie:
źródło
źródło
http://snipplr.com/view/51108/nested-array-search-by-value-or-key/
źródło
źródło
Potrzebowałem czegoś podobnego, ale aby wyszukać tablicę wielowymiarową według wartości ... Wziąłem przykład Johna i napisałem
Mam nadzieję, że komuś to pomoże :)
źródło
To jest poprawiona funkcja z tej, którą opublikował John K. ... Muszę pobrać tylko określony klucz z tablicy i nic ponad nim.
źródło
I inna wersja, która zwraca wartość klucza z elementu tablicy, w którym wartość została znaleziona (bez rekursji, zoptymalizowana pod kątem szybkości):
Dziękuję wszystkim, którzy tutaj napisali.
źródło
źródło
Jeśli chcesz wyszukać tablicę kluczy, to dobrze
Klucze nie zostaną nadpisane, ponieważ każdy zestaw wartości klucz => będzie w oddzielnej tablicy w wynikowej tablicy.
Jeśli nie chcesz zduplikowanych kluczy, użyj tego
źródło