Код:
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)
.
$key
не существует в массиве? Не лучше ли это сделатьif (array_key_exists($key, $array) && $array[$key] == $value) {
?$value
который есть,null
и функция не работает ...array empty
... Как получить массив, даже если$value
=null
? какsearch($array, 'id', null)
?Как насчет версии SPL вместо? Это сэкономит вам немного времени:
Что замечательно, так это то, что в основном один и тот же код будет перебирать каталог для вас, используя RecursiveDirectoryIterator вместо RecursiveArrayIterator. SPL - это Роксор.
Единственный облом SPL в том, что он плохо документирован в сети. Но несколько книг по PHP посвящены некоторым полезным деталям, в частности, Pro PHP; и вы можете, вероятно, Google для получения дополнительной информации, тоже.
источник
Ссылка: http://php.net/manual/en/function.array-filter.php
источник
Вернулся, чтобы опубликовать это обновление для тех, кому нужна подсказка по оптимизации этих ответов, особенно замечательный ответ Джона Кугельмана выше.
Его опубликованная функция работает нормально, но мне пришлось оптимизировать этот сценарий для обработки 12 000 строк результатов. Функция занимала вечные 8 секунд, чтобы просмотреть все записи, оооочень долго.
Мне просто нужна была функция, чтобы остановить поиск и вернуться, когда совпадение было найдено. То есть, если мы ищем customer_id, мы знаем, что в результирующем наборе есть только один, и как только мы находим customer_id в многомерном массиве, мы хотим вернуться.
Вот оптимизированная по скорости (и значительно упрощенная) версия этой функции для всех, кто в ней нуждается. В отличие от другой версии, он может обрабатывать только одну глубину массива, не повторяется и не объединяет несколько результатов.
Это сбило задачу, чтобы сопоставить 12 000 записей с 1,5 сек. Все еще очень дорого, но гораздо разумнее.
источник
Незначительное улучшение быстрой версии.
источник
Будьте осторожны с алгоритмами линейного поиска (вышеупомянутые являются линейными) в многомерных массивах, поскольку они имеют сложную сложность, поскольку его глубина увеличивает количество итераций, необходимых для обхода всего массива. Например:
потребуется не более 200 итераций, чтобы найти то, что вы ищете (если стрелка была в [100] [1]), с подходящим алгоритмом.
Линейные алгоритмы в этом случае работают при O (n) (порядок общего числа элементов во всем массиве), это плохо, миллион записей (например, массив 1000x100x10) потребует в среднем 500 000 итераций, чтобы найти стрелку. И что будет, если вы решите изменить структуру многомерного массива? И PHP запускает рекурсивный алгоритм, если ваша глубина превышает 100. Информатика может сделать лучше:
Где возможно, всегда используйте объекты вместо многомерных массивов:
и примените пользовательский интерфейс и функцию компаратора, чтобы отсортировать и найти их:
Вы можете
uasort()
использовать собственный компаратор, если вам хочется приключений, вы должны реализовать свои собственные коллекции для своих объектов, которые могут сортировать их и управлять ими (я всегда расширяю ArrayObject, чтобы включить функцию поиска как минимум).Как только они отсортированы (uasort равен O (n log n), что так же хорошо, как и по произвольным данным), двоичный поиск может выполнить операцию за O (log n), то есть миллион записей занимает всего ~ 20 итераций, чтобы поиск. Насколько я знаю, пользовательский двоичный поиск компаратора не реализован в PHP (
array_search()
использует естественное упорядочение, которое работает со ссылками на объекты, а не с их свойствами), вам придется реализовать это самостоятельно, как я.Этот подход более эффективен (больше нет глубины) и, что более важно, универсален (предполагается, что вы применяете сопоставимость с помощью интерфейсов), поскольку объекты определяют способ их сортировки, поэтому вы можете бесконечно перерабатывать код. Гораздо лучше =)
источник
Вот решение:
источник
источник
http://snipplr.com/view/51108/nested-array-search-by-value-or-key/
источник
источник
Мне нужно было что-то подобное, но для поиска многомерного массива по значению ... Я взял пример Джона и написал
Надеюсь, это кому-нибудь поможет :)
источник
Это пересмотренная функция от той, которую написал Джон К. ... Мне нужно взять только определенный ключ в массиве и ничего над ним.
источник
И еще одна версия, которая возвращает значение ключа из элемента массива, в котором это значение найдено (без рекурсии, оптимизировано для скорости):
Спасибо всем, кто разместил здесь.
источник
источник
Если вы хотите найти массив ключей, это хорошо
Ключи не будут перезаписываться, потому что каждый набор значений key => будет находиться в отдельном массиве в результирующем массиве.
Если вы не хотите дублировать ключи, используйте этот
источник