Поиск всех совпадений в массиве php. PHP: array_search — быстрый поиск по массиву

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

Сравнил скорость поиска в массиве с помощью этой функции с обычным перебором массива в циклах foreach и while. На 10-100 элементах массива разница незаметна да и время столь мало, что им можно принебречь. А вот для больших массивов разница оказалась весьма существенной. С увеличением размера массива на порядок, значительно увеличивалось и время поиска. При ста тысячах элементов скорость foreach падала до 0,013 секунды, а while - до 0,017, при том что array_search() тоже замедлился, но все-таки остался на порядок быстрее - 0.004 секунды. Для большого скрипта, работающего с большими массивами замена поиска в цикле на поиск с помощью array_search() будет вовсе не «блошиной оптимизацией».

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

UPD: нужен программистский склад ума, тоже нужен! И внимательность с памятью не помешают (навеяно break и range:)

Под хабракатом код скрипта, которым подсчитывал время:

$mass=100000; // число значений в массиве в котором будем искать
$search=50000; // в массиве будем искать это значение
$first_result=array(); // массив результатов, для вычисления среднего значения первого варианта
$second_result=array(); // массив результатов, для вычисления среднего значения второго варианта
$third_result=array(); // массив результатов, для вычисления среднего значения третьего варианта

// создаем и наполняем массив
$test_array = range(0, $mass-1); // спасибо SelenIT))

/*
$test_array=array();
for ($i=0; $i<$mass; $i++)
{
$test_array=$i;
}
*/

// цикл для подсчета средних значений
for ($d=0; $d<30; $d++) {

//*************** Поиск с помощью array_search *******************

// Запускаем подсчет времени
$time_start = microtime(1);
// поиск
$key = array_search($search, $test_array, true);
// если нашли
if ($key!==FALSE) // надо именно!== а не!=, ведь номер первого элемента - 0
{
echo $test_array[$key];
}
$time_end = microtime(1);
// конец подсчета времени

// пишем в массив значений
$first_result= $time_end - $time_start;

//*************** Поиск по массиву с циклом foreach *******************

// Запускаем подсчет времени
$time_start = microtime(1);
// сам поиск
foreach ($test_array as $ta)
{
if ($ta==$search)
{
echo $ta;
break;
}
}
$time_end = microtime(1);
// конец подсчета времени

// пишем в массив значений
$second_result= $time_end - $time_start;

//*************** Поиск по массиву с циклом while *******************

// Запускаем подсчет времени
$time_start = microtime(1);

// определяем длину массива
$count=count($test_array);
$j=0;
// сам поиск
while ($j<$count)
{
if ($test_array[$j]==$search) // если нашли
{
echo $test_array[$j];
break;
}
$j++;
}
$time_end = microtime(1);
// конец подсчета времени

// пишем в массив значений
$third_result= $time_end - $time_start;
}

$srednee1=array_sum ($first_result)/count($first_result);
$srednee2=array_sum ($second_result)/count($second_result);
$srednee3=array_sum ($third_result)/count($third_result);

Printf("первый код выполнен в среднем за: %.7f секунды", $srednee1);
printf("второй код выполнен в среднем за: %.7f секунды", $srednee2);
printf("третий код выполнен в среднем за: %.7f секунды", $srednee3);

// результат:
// первый код выполнен в среднем за: 0.0000295 секунды
// второй код выполнен в среднем за: 0.0153386 секунды
// третий код выполнен в среднем за: 0.0226001 секунды

(PHP 4 >= 4.0.5, PHP 5)

array_search -- Осуществляет поиск данного значения в массиве и возвращает соответствующий ключ в случае удачи

Описание

mixed array_search (mixed needle, array haystack [, bool strict])

Ищет в haystack значение needle и возвращает ключ, если таковое присутствует в массиве, FALSE в противном случае.

Замечание: Если needle является строкой, производится регистро-зависимое сравнение.

Замечание: До PHP 4.2.0, array_search() при неудаче возвращала NULL вместо FALSE .

Если вы передадите значение TRUE в качестве необязательного третьего параметра strict , функция array_search() также проверит тип needle в массиве haystack .

Если needle присутствует в haystack более одного раза, будет возвращён первый найденный ключ. Для того, чтобы возвратить ключи для всех найденных значений, используйте функцию array_keys() с необязательным параметром search_value .


Пример 1. Пример использования array_search()

$array = array(0 => "blue" , 1 => "red" , 2 => 0x000000 , 3 => "green" , 4 => "red" );$key = array_search ("red" , $array ); // $key = 1;
$key = array_search ("green" , $array ); // $key = 2; (0x000000 == 0 == "green")
$key = array_search ("green" , $array , true ); // $key = 3;
?>
Внимание

Эта функция может возвращать как логическое значение FALSE , так и не относящееся к логическому типу значение, которое приводится к FALSE , например, 0 или "". За более подробной информации обратитесь к разделу Булев тип . Используйте оператор === для проверки значения, возвращаемого этой функцией.

из многомерном (18)

Я изменил один из примеров ниже описание функции array_search . Функция searchItemsByKey возвращает все значения по $ key из многомерного массива (N уровней). Возможно, это было бы полезно для кого-то. Пример:

$arr = array("XXX"=>array("YYY"=> array("AAA"=> array("keyN" =>"value1")), "ZZZ"=> array("BBB"=> array("keyN" => "value2")) //.....)); $result = searchItemsByKey($arr,"keyN"); print "

";
print_r($result);
print "
";
// OUTPUT
Array
( => value1
 => value2)
 

Код функции:

Function searchItemsByKey($array, $key) { $results = array(); if (is_array($array)) { if (isset($array[$key]) && key($array)==$key) $results = $array[$key]; foreach ($array as $sub_array) $results = array_merge($results, searchItemsByKey($sub_array, $key)); } return $results; }

У меня есть массив, где я хочу искать uid и получить ключ от массива.

Примеры

Предположим, что мы имеем следующий двумерный массив:

$userdb = array(array("uid" => "100", "name" => "Sandra Shush", "pic_square" => "urlof100"), array("uid" => "5465", "name" => "Stefanie Mcmohn", "pic_square" => "urlof100"), array("uid" => "40489", "name" => "Michael", "pic_square" => "urlof40489"));

Вызов функции search_by_uid(100) (uid первого пользователя) должен вернуть 0 .

Вызов функции search_by_uid(40489) должен возвращать 2 .

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

Исходя из превосходного ответа Якуба, вот более обобщенный поиск, который позволит указать ключ (а не только для uid):

Function searcharray($value, $key, $array) { foreach ($array as $k => $val) { if ($val[$key] == $value) { return $k; } } return null; }

Использование: $results = searcharray("searchvalue", searchkey, $array);

Function searchForId($id, $array) { foreach ($array as $key => $val) { if ($val["uid"] === $id) { return $key; } } return null; }

Это сработает. Вы должны называть это следующим образом:

$id = searchForId("100", $userdb);

Важно знать, что если вы используете === сравниваемые типы операторов должны быть точно такими же, в этом примере вам нужно искать string или просто использовать == вместо === .

На основании ответа angoru . В более поздних версиях PHP (>= 5.5.0) вы можете использовать однострочный.

$key = array_search("100", array_column($userdb, "uid"));

Несмотря на то, что это старый вопрос и есть принятый ответ, я подумал, что я бы предложил одно изменение принятому ответу. Итак, в первую очередь, я согласен, что принятый ответ здесь верен.

Function searchArrayKeyVal($sKey, $id, $array) { foreach ($array as $key => $val) { if ($val[$sKey] == $id) { return $key; } } return false; }

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

// Array Data Of Users $userdb = array (array ("uid" => "100","name" => "Sandra Shush","url" => "urlof100"), array ("uid" => "5465","name" => "Stefanie Mcmohn","url" => "urlof100"), array ("uid" => "40489","name" => "Michael","url" => "urlof40489"),); // Obtain The Key Of The Array $arrayKey = searchArrayKeyVal("uid", "100", $userdb); if ($arrayKey!==false) { echo "Search Result: ", $userdb[$arrayKey]["name"]; } else { echo "Search Result can not be found"; }

If(! function_exists("arraySearchMulti")){ function arraySearchMulti($search,$key,$array,$returnKey=false) { foreach ($array as $k => $val) { if (isset($val[$key])) { if ((string)$val[$key] == (string)$search) { return ($returnKey ? $k: $val); } }else{ return (is_array($val) ? arraySearchMulti($search,$key,$val,$returnKey) : null); } } return null; }}

вы можете использовать эту функцию; https://github.com/serhatozles/ArrayAdvancedSearch

="2""; $Array = array("a" => array("d" => "2"), array("a" => "Example World","b" => "2"), array("c" => "3"), array("d" => "4"),); $Result = ArraySearch($Array,$query,1); echo "

";
print_r($Result);
echo "
"; // Output: // Array // (// => Array // (// [a] => Example World // [b] => 2 //) // //)

Если вопрос, т.е.

$a = [ [ "_id" => "5a96933414d48831a41901f2", "discount_amount" => 3.29, "discount_id" => "5a92656a14d488570c2c44a2", ], [ "_id" => "5a9790fd14d48879cf16a9e8", "discount_amount" => 4.53, "discount_id" => "5a9265b914d488548513b122", ], [ "_id" => "5a98083614d488191304b6c3", "discount_amount" => 15.24, "discount_id" => "5a92806a14d48858ff5c2ec3", ], [ "_id" => "5a982a4914d48824721eafe3", "discount_amount" => 45.74, "discount_id" => "5a928ce414d488609e73b443", ], [ "_id" => "5a982a4914d48824721eafe55", "discount_amount" => 10.26, "discount_id" => "5a928ce414d488609e73b443", ], ];

Function searchForId($id, $array) { $did=0; $dia=0; foreach ($array as $key => $val) { if ($val["discount_id"] === $id) { $dia +=$val["discount_amount"]; $did++; } } if($dia != "") { echo $dia; var_dump($did); } return null; }; print_r(searchForId("5a928ce414d488609e73b443",$a));

Попробуйте это также

Function search_in_array($srchvalue, $array) { if (is_array($array) && count($array) > 0) { $foundkey = array_search($srchvalue, $array); if ($foundkey === FALSE) { foreach ($array as $key => $value) { if (is_array($value) && count($value) > 0) { $foundkey = search_in_array($srchvalue, $value); if ($foundkey != FALSE) return $foundkey; } } } else return $foundkey; } }

$a = ["x" => ["eee", "ccc"], "b" => ["zzz"]]; $found = null; $search = "eee"; array_walk($a, function ($k, $v) use ($search, &$found) { if (in_array($search, $k)) { $found = $v; } }); var_dump($found);

Вот один лайнер для того же,

$pic_square = $userdb["pic_square"];

Вот мой пример и, пожалуйста, обратите внимание, что это мой первый ответ. Я достал массив param, потому что мне нужно было искать только один конкретный массив, но вы могли бы легко добавить его. Я хотел по существу искать больше, чем просто uid.

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

/** * @param array multidimensional * @param string value to search for, ie a specific field name like name_first * @param string associative key to find it in, ie field_name * * @return array keys. */ function search_revisions($dataArray, $search_value, $key_to_search) { // This function will search the revisions for a certain value // related to the associative key you are looking for. $keys = array(); foreach ($dataArray as $key => $cur_value) { if ($cur_value[$key_to_search] == $search_value) { $keys = $key; } } return $keys; }

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

В этом втором примере показано, где значение («Тейлор») найдено в определенном ассоциативном ключе (first_name). И другое значение (true) найдено в другом ассоциативном ключе (используется) и возвращает все соответствия (Ключи, в которых люди с именем «Тейлор» И используются).

/** * @param array multidimensional * @param string $search_value The value to search for, ie a specific "Taylor" * @param string $key_to_search The associative key to find it in, ie first_name * @param string $other_matching_key The associative key to find in the matches for employed * @param string $other_matching_value The value to find in that matching associative key, ie true * * @return array keys, ie all the people with the first name "Taylor" that are employed. */ function search_revisions($dataArray, $search_value, $key_to_search, $other_matching_value = null, $other_matching_key = null) { // This function will search the revisions for a certain value // related to the associative key you are looking for. $keys = array(); foreach ($dataArray as $key => $cur_value) { if ($cur_value[$key_to_search] == $search_value) { if (isset($other_matching_key) && isset($other_matching_value)) { if ($cur_value[$other_matching_key] == $other_matching_value) { $keys = $key; } } else { // I must keep in mind that some searches may have multiple // matches and others would not, so leave it open with no continues. $keys = $key; } } } return $keys; }

Использование функции

$data = array(array("cust_group" => 6, "price" => 13.21, "price_qty" => 5), array("cust_group" => 8, "price" => 15.25, "price_qty" => 4), array("cust_group" => 8, "price" => 12.75, "price_qty" => 10)); $findKey = search_revisions($data,"8", "cust_group", "10", "price_qty"); print_r($findKey);

Результат

Array ( => 2)

/** * searches a simple as well as multi dimension array * @param type $needle * @param type $haystack * @return boolean */ public static function in_array_multi($needle, $haystack){ $needle = trim($needle); if(!is_array($haystack)) return False; foreach($haystack as $key=>$value){ if(is_array($value)){ if(self::in_array_multi($needle, $value)) return True; else self::in_array_multi($needle, $value); } else if(trim($value) === trim($needle)){//visibility fix// error_log("$value === $needle setting visibility to 1 hidden"); return True; } } return False; }

Если вы используете (PHP 5> = 5.5.0), вам не нужно писать свою собственную функцию для этого, просто напишите эту строку, и все будет готово.

Если вы хотите получить только один результат:

$key = array_search(40489, array_column($userdb, "uid"));

Для нескольких результатов

$keys = array_keys(array_column($userdb, "uid"), 40489);

Если у вас есть ассоциативный массив, как указано в комментариях, вы можете сделать это с помощью:

$keys = array_keys(array_combine(array_keys($userdb), array_column($userdb, "uid")),40489);

Если вы используете PHP <5.5.0, вы можете использовать этот backport , спасибо ramsey!

Обновление. Я делаю несколько простых тестов, и форма с несколькими результатами, кажется, самая быстрая, даже быстрее, чем пользовательская функция Jakub!

В более поздних версиях PHP (> = 5.5.0) вы можете использовать этот однострочный:

$key = array_search("100", array_column($userdb, "uid"));

Развернув на созданную функцию @mayhem, этот пример будет скорее «нечетким» поиском, если вы просто захотите сопоставить часть (большую часть) строки поиска:

Function searchArrayKeyVal($sKey, $id, $array) { foreach ($array as $key => $val) { if (strpos(strtolower($val[$sKey]), strtolower(trim($id))) !== false) { return $key; } } return false; }

Например, значение в массиве - Добро пожаловать в Нью-Йорк! и вам нужен первый экземпляр только «Нью-Йорк!».

Мне пришлось использовать функцию un, которая находит все элементы в массиве. Поэтому я изменил функцию, выполняемую Якубом Трунечком следующим образом:

Function search_in_array_r($needle, $array) { $found = array(); foreach ($array as $key => $val) { if ($val == $needle) { array_push($found, $val); } } if (count($found) != 0) return $found; else return null; }

$search1 = "demo"; $search2 = "bob"; $arr = array("0" => "hello","1" => "test","2" => "john","3" => array("0" => "martin", "1" => "bob"),"4" => "demo"); foreach ($arr as $value) { if (is_array($value)) { if (in_array($search2, $value)) { echo "successsfully"; //execute your code } } else { if ($value == $search1) { echo "success"; } } }

Если возможно, введите типы параметров. Но он работает только с простыми типами, такими как int, bool и float.

$unsafe_variable = $_POST["user_id"]; $safe_variable = (int)$unsafe_variable ; mysqli_query($conn, "INSERT INTO table (column) VALUES ("" . $safe_variable . "")");

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

Функции для поиска в массиве :
array_search — служит для поиска значения в массиве. В случае удачи она возвращает ключ искомого значения, если ничего не найдено — возвращает FALSE. До версии PHP 4.2.0, array_search() при неудаче возвращала NULL, а не FALSE.

Синтаксис функции mixed array_search (mixed needle, array haystack [, bool strict]).

foreach (array_expression as $value)
statement
foreach (array_expression as $key => $value)
statement

Пример использования функции с конструкцией foreach для поиска элемента массива, возвращает TRUE при успехе

Синтаксис конструкции
while (expr)
statement

Возвращает ключ элемента массива при успехе

Из приведенной таблицы замеров видно, что функция array_search , показывает наилучший результат как при поиске в малых так и больших массивах. При этом время поиска спомощью циклов значительно увеличивается в зависимости от размера массива.