Intereting Posts
char с помощью php file_get_contents () и API диаграммы Google? Как скопировать электронную почту с Gmail на мой сервер с помощью PHP IMAP? mysqli фатальная ошибка: индекс не используется в запросе / подготовленном сообщении jQuery анализирует / отображает данные json от php json_encode Потяните и покажите изображения в галерее веб-сайтов из Dropbox Directory Как вы можете уловить ошибку «отказа в разрешении» при использовании fopen в PHP без использования try / catch? Невозможность настроить сумму товара В последнее время метод Laravel 4 all () начал возвращать коллекцию Eloquent – почему? Хранение массивов в файлах cookie Как использовать веб-службы GeoNames с помощью PHP Простой шаблон HTML DOM в атрибуте Проверка имени пользователя php на базе данных, когда пользователь уже занят Как сохранить AJAX от освежающего сайта Задайте значение переменной в одной функции и используйте в других функциях при вызове непосредственно из ссылки в codeigniter Как сортировать по номерам сначала с Oracle SQL-запроса?

Как выполнить поиск по key => значение в многомерном массиве в PHP

Есть ли какой-либо быстрый способ получить все подмассивы, где пара ключевых значений была найдена в многомерном массиве? Я не могу сказать, насколько глубоким будет массив.

Простой пример массива:

$arr = array(0 => array(id=>1,name=>"cat 1"), 1 => array(id=>2,name=>"cat 2"), 2 => array(id=>3,name=>"cat 1") ); 

Когда я ищу ключ = имя и значение = "cat 1", функция должна возвращать:

 array(0 => array(id=>1,name=>"cat 1"), 1 => array(id=>3,name=>"cat 1") ); 

Я думаю, функция должна быть рекурсивной, чтобы перейти на самый глубокий уровень.

Код:

 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')); 

Вывод:

 Array ( [0] => Array ( [id] => 1 [name] => cat 1 ) [1] => Array ( [id] => 3 [name] => cat 1 ) ) 

Если эффективность важна, вы можете написать ее так, чтобы все рекурсивные вызовы сохраняли свои результаты в одном и том же временном массиве $results а не объединяли массивы вместе:

 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); } } 

Ключ в том, что search_r принимает свой четвертый параметр по ссылке, а не по значению; амперсанд & имеет решающее значение.

FYI: Если у вас установлена ​​более старая версия PHP, вам нужно указать часть прохода по ссылке в search_r а не в ее объявлении. То есть, последняя строка становится search_r($subarray, $key, $value, &$results) .

Как насчет версии SPL ? Это спасет вас от ввода:

 // I changed your input example to make it harder and // to show it works at lower depths: $arr = array(0 => array('id'=>1,'name'=>"cat 1"), 1 => array(array('id'=>3,'name'=>"cat 1")), 2 => array('id'=>2,'name'=>"cat 2") ); //here's the code: $arrIt = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr)); foreach ($arrIt as $sub) { $subArray = $arrIt->getSubIterator(); if ($subArray['name'] === 'cat 1') { $outputArray[] = iterator_to_array($subArray); } } 

Замечательно то, что в основном один и тот же код будет перебирать через каталог для вас, используя рекурсивныйDirectoryIterator вместо рекурсивногоArrayIterator. SPL – это роксор.

Единственным обломком SPL является то, что он плохо документирован в Интернете. Но несколько книг PHP посвящены некоторым полезным деталям, особенно Pro PHP; и вы можете, вероятно, google и получить дополнительную информацию.

 <?php $arr = array(0 => array("id"=>1,"name"=>"cat 1"), 1 => array("id"=>2,"name"=>"cat 2"), 2 => array("id"=>3,"name"=>"cat 1") ); $arr = array_filter($arr, function($ar) { return ($ar['name'] == 'cat 1'); //return ($ar['name'] == 'cat 1' AND $ar['id'] == '3');// you can add multiple conditions }); echo "<pre>"; print_r($arr); ?> 

Ссылка: http://php.net/manual/en/function.array-filter.php

Вернулся, чтобы опубликовать это обновление для тех, кто нуждается в совете по оптимизации этих ответов, в частности, отличный ответ Джона Кугельмана выше.

Его опубликованная функция работает нормально, но мне пришлось оптимизировать этот сценарий для обработки набора результатов в 12 000 строк. Функция выполняла вечные 8 секунд, чтобы пройти через все записи, waaaaaay слишком долго.

Я просто нуждался в функции STOP для поиска и возврата, когда совпадение найдено. То есть, если вы ищете client_id, мы знаем, что у нас есть только один в наборе результатов, и как только мы найдем customer_id в многомерном массиве, мы хотим вернуться.

Вот оптимизированная по скорости (и значительно упрощенная) версия этой функции для всех, кто в ней нуждается. В отличие от другой версии, она может обрабатывать только одну глубину массива, не рекурсивно и не позволяет слить несколько результатов.

 // search array for specific key = value public function searchSubArray(Array $array, $key, $value) { foreach ($array as $subarray){ if (isset($subarray[$key]) && $subarray[$key] == $value) return $subarray; } } 

Это сбило задачу, чтобы соответствовать 12 000 записей за 1,5 секунды. Все еще очень дорого, но гораздо более разумно.

 if (isset($array[$key]) && $array[$key] == $value) 

Небольшое преимущество быстрой версии.

Будьте осторожны с алгоритмами линейного поиска (приведенные выше линейными) в многомерных массивах, поскольку они усложняют сложность, так как ее глубина увеличивает количество итераций, необходимых для прохождения по всему массиву. Например:

 array( [0] => array ([0] => something, [1] => something_else)) ... [100] => array ([0] => something100, [1] => something_else100)) ) 

потребовалось бы всего 200 итераций, чтобы найти то, что вы ищете (если игла была в [100] [1]), с подходящим алгоритмом.

Линейные алгоритмы в этом случае выполняются в O (n) (общее количество элементов в целом массиве), это плохо, миллион записей (например, массив 1000x100x10) потребует в среднем 500 000 итераций, чтобы найти иглу. Также, что произойдет, если вы решите изменить структуру вашего многомерного массива? И PHP выработал бы рекурсивный алгоритм, если бы ваша глубина была больше 100. Информатика может сделать лучше:

По возможности всегда используйте объекты вместо многомерных массивов:

 ArrayObject( MyObject(something, something_else)) ... MyObject(something100, something_else100)) ) 

и примените пользовательский интерфейс и функцию компаратора для их сортировки и поиска:

 interface Comparable { public function compareTo(Comparable $o); } class MyObject implements Comparable { public function compareTo(Comparable $o){ ... } } function myComp(Comparable $a, Comparable $b){ return $a->compareTo($b); } 

Вы можете использовать uasort() для использования пользовательского компаратора, если вы чувствуете себя авантюристом, вы должны реализовать свои собственные коллекции для своих объектов, которые могут их сортировать и управлять ими (я всегда расширяю ArrayObject, чтобы включить функцию поиска, по крайней мере).

 $arrayObj->uasort("myComp"); 

Когда они сортируются (uasort – это O (n log n), что так же хорошо, как и по произвольным данным), двоичный поиск может выполнять операцию в O (log n), т. Е. Миллион записей занимает всего 20 итераций поиск. Насколько мне известно, бинарный поиск не выполняется в PHP ( array_search() использует естественное упорядочение, которое работает с объектными ссылками, а не их свойствами), вы должны реализовать это свое я, как я.

Этот подход более эффективен (больше нет глубины) и, что более важно, универсален (при условии, что вы обеспечиваете сопоставимость с использованием интерфейсов), поскольку объекты определяют, как они сортируются, поэтому вы можете бесконечно перерабатывать код. Гораздо лучше =)

 $result = array_filter($arr, function ($var) { $found = false; array_walk_recursive($var, function ($item, $key) use (&$found) { $found = $found || $key == "name" && $item == "cat 1"; }); return $found; }); 

http://snipplr.com/view/51108/nested-array-search-by-value-or-key/

 <?php //PHP 5.3 function searchNestedArray(array $array, $search, $mode = 'value') { foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $key => $value) { if ($search === ${${"mode"}}) return true; } return false; } $data = array( array('abc', 'ddd'), 'ccc', 'bbb', array('aaa', array('yyy', 'mp' => 555)) ); var_dump(searchNestedArray($data, 555)); 
 function in_multi_array($needle, $key, $haystack) { $in_multi_array = false; if (in_array($needle, $haystack)) { $in_multi_array = true; }else { foreach( $haystack as $key1 => $val ) { if(is_array($val)) { if($this->in_multi_array($needle, $key, $val)) { $in_multi_array = true; break; } } } } return $in_multi_array; } 

Мне нужно было что-то подобное, но искать многомерный массив по значению … Я взял пример Джона и написал

 function _search_array_by_value($array, $value) { $results = array(); if (is_array($array)) { $found = array_search($value,$array); if ($found) { $results[] = $found; } foreach ($array as $subarray) $results = array_merge($results, $this->_search_array_by_value($subarray, $value)); } return $results; } 

Надеюсь, это поможет кому-то 🙂

Это пересмотренная функция от той, которую написал Джон К. … Мне нужно захватить только конкретный ключ в массиве и ничего выше него.

 function search_array ( $array, $key, $value ) { $results = array(); if ( is_array($array) ) { if ( $array[$key] == $value ) { $results[] = $array; } else { foreach ($array as $subarray) $results = array_merge( $results, $this->search_array($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_array($arr, 'name', 'cat 1')); 

Вот решение:

 <?php $students['e1003']['birthplace'] = ("Mandaluyong <br>"); $students['ter1003']['birthplace'] = ("San Juan <br>"); $students['fgg1003']['birthplace'] = ("Quezon City <br>"); $students['bdf1003']['birthplace'] = ("Manila <br>"); $key = array_search('Delata Jona', array_column($students, 'name')); echo $key; ?> 

И еще одна версия, которая возвращает значение ключа из элемента массива, в котором найденное значение (без рекурсии, оптимизировано для скорости):

 // if the array is $arr['apples'] = array('id' => 1); $arr['oranges'] = array('id' => 2); //then print_r(search_array($arr, 'id', 2); // returns Array ( [oranges] => Array ( [id] => 2 ) ) // instead of Array ( [0] => Array ( [id] => 2 ) ) // search array for specific key = value function search_array($array, $key, $value) { $return = array(); foreach ($array as $k=>$subarray){ if (isset($subarray[$key]) && $subarray[$key] == $value) { $return[$k] = $subarray; return $return; } } } 

Спасибо всем, кто разместил здесь.

 function findKey($tab, $key){ foreach($tab as $k => $value){ if($k==$key) return $value; if(is_array($value)){ $find = findKey($value, $key); if($find) return $find; } } return null; }