preg_match VS. stripos in PHP - php

The target is to check a product description and to identify different characteristics/product options. The input data has the following structure:
// TABLE WITH INPUT DATA. STRUCTURE: PRODUCT_CATEGORY [0], PRODUCT_NUMBER[1], DESCRIPTION OF AN OPTION [2]. THE INPUT DATA TABLE CAN CONSIST OF UP TO 400-500 ROWS
$input_product_data = array (
array('AAAA','1111','Chimney with red bricks in the center of the room'),
array('BBBB','2222','Two wide windows in the main floor'),
array('BBBB','2233','Plastic window has to be changed later'),
array('CCCC','3333','Roof tiles renewed in 2015'),
array('NULL','4444','Floor has been renovated for two years. Currently it has ground in wood.'),
array('NULL','NULL','Beautiful door in green color built at begin of 20th century')
);
There are 3 different constelations to indicate a product option:
Only by search string within product description,
Example:
Input data: array('NULL','NULL','Beautiful door in green color built at begin of 20th century')
Search string: 'green color' within PRODUCT_DESCRIPTION
Result: Available
By search string within product description + product category:
Example:
Input data: array('CCCC','NULL','Roof tiles renewed in 2015'),
Search strings: 'CCCC' within PRODUCT_CATEGORY + 'green color' within PRODUCT_DESCRIPTION
Result: Available
By search string within product description + product category + product number.
Example:
Input data: array('AAAA','1111','Chimney with red bricks in the center of the room')
Search strings: 'AAAA' within PRODUCT_CATEGORY + '1111' within PRODUCT_NUMBER + 'Chimney' within PRODUCT_DESCRIPTION
Result: Available
IMPORTANT:
The table with input data per product can consist of up to 450 description rows.
The search strings can be defined many times ( e. g. 10 different search strings for the option "Windows" like "windows in the floor", "big windows", "window without glas" etc.).
The start set of rules (combinations of product description + product category + product number) will consist of ca. 3000 rows and will be extented permanently by business guys.
REALIZATION VARIANT A (by use of preg_match):
// TABLE FOR PRODUCT OPTIONS. STRUCTURE: ID[0], OPTION NAME[1], OPTION CATEGORY[2], OPTION-FAMILY[3], PROD.-NR[4], REG. EXPRESSION[5], PRIORITY[6], OUTPUT[7]
$ct_product_options = array (
array('0001', 'Chimney', 'Additional options', '/^AAAA/', '/9999/', '/^Chimney with./', '0', 'Available'),
array('0002', 'Material of ground floor', 'Additional options', '/NULL/', '/^4444$/', '/.wood./', '0', 'Wood'),
array('0003', 'Roof tiles', 'Basic options', '/^CCCC/', '/0022/', '/^Roof tiles./', '0', 'Available'),
array('0004', 'Windows', 'Basic options', '/^B...$/', '/^2.../', '/.window$/', '0', 'Available'),
array('0004', 'Windows', 'Basic options', '/^B...$/', '/^2.../', '/.wide windows./', '0', 'Available'),
array('0005', 'Door color', 'Basic options', '/NULL/', '/NULL/', '/green/', '0', 'Green'),
array('0006', 'Air condition', 'Additional options', '/NULL/', '/NULL/', '/^Air condition made in Japan/', '0', 'Green')
);
// FOR LOOP TO MAKE COMPARISON BETWEEN INPUT PRODUCT DATA AND PREDEFINED CUST. STRINGS
$matches_array = array();
foreach ($input_product_data as [$product_family, $product_number, $product_description]) {
foreach($ct_product_options as [$option_id, $option_name, $option_category, $product_family_reg_exp, $product_number_reg_exp, $regular_expression, $priority, $output]) {
if (preg_match($regular_expression, $product_description) == 1
&& preg_match($product_family_reg_exp, $product_family) == 1 ||
preg_match($regular_expression, $product_description) == 1
&& preg_match($product_number_reg_exp, $product_number) == 1) {
$matches_array [] = array("id" => $option_id, "option_name" => $option_name, "option_category" => $option_category, "output"=> $output);
}
else {
if (empty($product_family) && empty($product_number)) {
if (preg_match($regular_expression, $product_description) == 1) {
$matches_array [] = array("id" => $option_id, "option_name" => $option_name, "option_category" => $option_category, "output"=> $output);
}
}
}
}
}
//echo "<pre>";
//print_r($matches_array);
// FUNCTION FOR DELETE DUBLICATES FROM ARRAY WITH MATCHES
function unique_multidimensional_array($array, $key) {
$temp_array = array();
$i = 0;
$key_array = array();
foreach($array as $val) {
if (!in_array($val[$key], $key_array)) {
$key_array[$i] = $val[$key];
$temp_array[$i] = $val;
}
$i++;
}
return $temp_array;
}
//echo "<br><h3>UNIQUE MATCHES</h3>";
// CALL OF THE FUNCTION TO GET UNIQUE MATCHES
$unique_matches = unique_multidimensional_array($matches_array, 'id');
sort($unique_matches);
//echo "<pre>";
//print_r($unique_matches);
// CALL OF THE FUNCTION TO CREATE LIST/ARRAY WITH ALL AVAILABLE PRODUCT OPTIONS
$list_all_product_options = unique_multidimensional_array($ct_product_options, 0);
$list_all_product_options_short = array();
foreach ($list_all_product_options as $option_item) {
$list_all_product_options_short[] = array("id" => $option_item[0], "option_name" => $option_item[1], "option_category" => $option_item[2]);
}
sort($list_all_product_options_short);
//echo "<h3>LIST WITH ALL PRODUCT OPTIONS (SHORT VERSION)</h3>\n";
//echo "<pre>";
//print_r($list_all_product_options_short);
$unique_matches = array_column($unique_matches, null, 'id');
foreach ($list_all_product_options_short as $key => $value) {
if (isset($unique_matches[$value['id']])) {
$result[$key] = array_merge($value, $unique_matches[$value['id']]);
} else {
$result[$key] = array_merge($value, ['output' => 'Not available']);
}
}
echo "<h3>FINAL RESULTS</h3>\n";
//echo "<pre><br>\n";
print_r($result);
The variant realized with preg_match works well and provide quite good flexibilty by defining of the regex. E. g. Instead to define the whole product number "2222" I can use only "/^2.../". Or I can combine many regex within one row by use of "|" (e. g. ".wide windows. | some window | etc."). The problem is that by real data volume 500 rows within $input_product_data and 3000 rows within $ct_product_options the code is quite slow.
REALIZATION VARIANT B (by use of stripos):
// INPUT DATA WITH PRODUCT DESCRIPTION. STRUCTURE: PROD. FAMILY, PROD. NUMBER, PRODUCT DESCRIPTION
$input_product_data = array (
array('AAAA','1111','Chimney with red bricks in the center of the room'),
array('BBBB','2222','Two wide windows in the main floor'),
array('BBBB','2233','Plastic window has to be changed later'),
array('CCCC','3333','Roof tiles renewed in 2015'),
array('NULL','4444','Floor has been renovated for two years. Currently it has ground in wood.'),
array('NULL','NULL','Beautiful door in green color built at begin of 20th century')
);
// CUSTOMIZING TABLE FOR PRODUCT OPTIONS. STRUCTURE: ID[0], OPTION NAME[1], OPTION CATEGORY[2], OPTION-FAMILY[3], PROD.-NR[4], REG. EXPRESSION[5], PRIORITY[6], OUTPUT[7]
$ct_product_options = array (
array('0001', 'Chimney', 'Additional options', 'AAAA', '9999', 'Chimney with', '0', 'Available'),
array('0002', 'Material of ground floor', 'Additional options', 'NULL', '4444', 'wood', '0', 'Wood'),
array('0003', 'Roof tiles', 'Basic options', 'CCCC', '0022', 'Roof tiles', '0', 'Available'),
array('0004', 'Windows', 'Basic options', 'BBBB', '2222', 'window', '0', 'Available'),
array('0004', 'Windows', 'Basic options', 'BBBB', '2222', 'wide windows', '0', 'Available'),
array('0005', 'Door color', 'Basic options', 'NULL', 'NULL', 'green', '0', 'Green'),
array('0006', 'Air condition', 'Additional options', 'NULL', 'NULL', 'Air condition made in Japan', '0', 'Green')
);
// IMPORTANT: THE REG. EXPRESSIONS CAN BE DEFINED MANY TIME (e. g. 10 DIFFERENT REG: EXPRESSIONS FOR WINDOW). POINTS "." REPRESENTS EMPTY SPACES WHICH ARE IMPORTANT TO INDETIFY EXACTLY AN OPTION.
// FOR LOOP TO MAKE COMPARISON BETWEEN INPUT PRODUCT DATA AND PREDEFINED CUST. STRINGS
$matches_array = array();
foreach ($input_product_data as [$product_family, $product_number, $product_description]) {
foreach($ct_product_options as [$option_id, $option_name, $option_category, $product_family_reg_exp, $product_number_reg_exp, $regular_expression, $priority, $output]) {
if (stripos($product_description, $regular_expression) !== false
&& stripos($product_family, $product_family_reg_exp) !== false ||
stripos($product_description, $regular_expression) !== false
&& stripos($product_number, $product_number_reg_exp) !== false) {
$matches_array [] = array("id" => $option_id, "option_name" => $option_name, "option_category" => $option_category, "output"=> $output);
}
else {
if (empty($product_family) && empty($product_number)) {
if (stripos($product_description, $regular_expression) !== false) {
$matches_array [] = array("id" => $option_id, "option_name" => $option_name, "option_category" => $option_category, "output"=> $output);
}
}
}
}
}
//echo "<pre>";
//print_r($matches_array);
// FUNCTION FOR DELETE DUBLICATES FROM ARRAY WITH MATCHES
function unique_multidimensional_array($array, $key) {
$temp_array = array();
$i = 0;
$key_array = array();
foreach($array as $val) {
if (!in_array($val[$key], $key_array)) {
$key_array[$i] = $val[$key];
$temp_array[$i] = $val;
}
$i++;
}
return $temp_array;
}
//echo "<br><h3>UNIQUE MATCHES</h3>";
// CALL OF THE FUNCTION TO GET UNIQUE MATCHES
$unique_matches = unique_multidimensional_array($matches_array, 'id');
sort($unique_matches);
//echo "<pre>";
//print_r($unique_matches);
// CALL OF THE FUNCTION TO CREATE LIST/ARRAY WITH ALL AVAILABLE PRODUCT OPTIONS
$list_all_product_options = unique_multidimensional_array($ct_product_options, 0);
$list_all_product_options_short = array();
foreach ($list_all_product_options as $option_item) {
$list_all_product_options_short[] = array("id" => $option_item[0], "option_name" => $option_item[1], "option_category" => $option_item[2]);
}
sort($list_all_product_options_short);
//echo "<h3>LIST WITH ALL PRODUCT OPTIONS (SHORT VERSION)</h3>\n";
//echo "<pre>";
//print_r($list_all_product_options_short);
// ::::::::::::::::::::::::::::::::::
$unique_matches = array_column($unique_matches, null, 'id');
foreach ($list_all_product_options_short as $key => $value) {
if (isset($unique_matches[$value['id']])) {
$result[$key] = array_merge($value, $unique_matches[$value['id']]);
} else {
$result[$key] = array_merge($value, ['output' => 'Not available']);
}
}
echo "<h3>FINAL RESULTS</h3>\n";
//echo "<pre><br>\n";
print_r($result);
It works much faster, but does not provide the felixibility of regex.
So, my questions:
Do you see any ways to optimize VARIANT A to get it faster or optimize VARIANT B to get it more flexible?
Especial question: How I can add the logic for the parameter PRIORITY from the table $ct_product_options?
The business logic is the following for it: As default all rows/rules have priority "0". But some of them will get priority ">0" (e. g. "1" or "2" etc.). The rule with highest priority should overwrite other rules.
E. g.
This rule with priority "0" identified windows in the house.
array('0004', 'Windows', 'Basic options', '/^B...$/', '/^2.../', '/.wide windows./', '0', 'Available')
At the same time this rule with priority "1" tells us that all windows are not available more. So, that means we have to get "Not available" within the final results.
array('0004', 'Windows', 'Basic options', '/^B...$/', '/^2.../', '/^Windows have been removed from the whole building last year/', '1', 'Not available')

Before optimizing the variants, I believe I should tell how I would implement a solution to solve generate the intended array.
I ran your code to understand better what should be the result. But instead of using print_r, I did this:
echo json_encode($result, JSON_PRETTY_PRINT);
I got this:
[
{
"id": "0001",
"option_name": "Chimney",
"option_category": "Additional options",
"output": "Available"
},
{
"id": "0002",
"option_name": "Material of ground floor",
"option_category": "Additional options",
"output": "Wood"
},
{
"id": "0003",
"option_name": "Roof tiles",
"option_category": "Basic options",
"output": "Available"
},
{
"id": "0004",
"option_name": "Windows",
"option_category": "Basic options",
"output": "Available"
},
{
"id": "0005",
"option_name": "Door color",
"option_category": "Basic options",
"output": "Green"
},
{
"id": "0006",
"option_name": "Air condition",
"option_category": "Additional options",
"output": "Not available"
}
]
I noticed each array element is an element from $ct_product_options mapped to some format. So, I used array_map like this:
$result = array_map(
fn($option) => [
'id' => $option[0],
'option_name' => $option[1],
'option_category' => $option[2],
'output' => get_option_output($option, $input_product_data),
],
$ct_product_options
);
Now I have to implement get_option_output. I think all those nested foreach and if in both A and B variants make the code hard to understand (besides how each line is indented). If I understand correctly your intentions, it seems this has a bug:
if (
preg_match($regular_expression, $product_description) == 1
&& preg_match($product_family_reg_exp, $product_family) == 1 ||
preg_match($regular_expression, $product_description) == 1
&& preg_match($product_number_reg_exp, $product_number) == 1) {
And you wanted to do something like this:
$productDescriptionMatches = preg_match($regular_expression, $product_description);
if (
(
$productDescriptionMatches
&& preg_match($product_family_reg_exp, $product_family)
) || (
$productDescriptionMatches
&& preg_match($product_number_reg_exp, $product_number)
)
) {
Which is equivalent to:
if (
preg_match($regular_expression, $product_description)
&& (
preg_match($product_family_reg_exp, $product_family)
|| preg_match($product_number_reg_exp, $product_number)
)
) {
If I counted everything correctly, and assuming you made that mistake, I believe you want something like this:
function some($array, $callback)
{
foreach ($array as $item) {
if ($callback($item)) {
return $item;
}
}
return false;
}
function get_option_output($option, $products)
{
$found = some(
$products,
fn($product) =>
(
preg_match($option[5], $product[2])
&& (
preg_match($option[3], $product[0])
|| preg_match($option[4], $product[1])
|| (
empty($product[0])
&& empty($product[1])
)
)
)
);
return $found ? $option[7] : 'Not available';
}
$result = array_map(
fn($option) => [
'id' => $option[0],
'option_name' => $option[1],
'option_category' => $option[2],
'output' => get_option_output($option, $input_product_data),
],
$ct_product_options
);
In average, the execution time of that code was: 0.0000189903259277 seconds. I ran 10,000 iterations.
Variant A took in average: 0.0000316595554352 seconds.
Variant B took in average: 0.0000314178943634 seconds.
The code I provided doesn't have nested loops and doesn't have to remove repeated elements and sorting them twice. But it's possible to make it run faster:
$result = [];
foreach ($ct_product_options as $option) {
foreach ($input_product_data as $product) {
$output = null;
$isAvailable =
(
preg_match($option[5], $product[2])
&& (
preg_match($option[3], $product[0])
|| preg_match($option[4], $product[1])
|| (
empty($product[0])
&& empty($product[1])
)
)
);
if ($isAvailable) {
$output = $option[7];
break;
}
}
$result []= [
'id' => $option[0],
'option_name' => $option[1],
'option_category' => $option[2],
'output' => $output ?? 'Not available',
];
}
It took, in average, 0.0000132960796356 seconds. But it's harder to understand.
That answers the first question. Use an array_map.
It also helps to answer the special question: change the function get_option_output accordingly.
If priority is the regular expression that should be used (and all the others should be ignored), then do something like this (also check if the priority is valid):
function get_option_output($option, $products)
{
$priority = (int)$option[6];
$found = find(
$products,
fn($product) => preg_match(
$option[3 + $priority],
$product[$priority]
)
);
return $found ? $option[7] : 'Not available';
}
If the one with the highest priority should be checked first, and the others should also be checked:
function some($array, $callback)
{
foreach ($array as $index => $item) {
if ($callback($item, $index)) {
return true;
}
}
return false;
}
function get_option_output($option, $products)
{
$priority = (int)$option[6];
$found = some(
$products,
fn($product) =>
preg_match($option[3 + $priority], $product[$priority])
|| some(
$product,
fn($text, $index) =>
$index !== $priority
&& preg_match($option[3 + $index], $product[$index])
)
);
return $found ? $option[7] : 'Not available';
}
If I didn't understand the details and something is missing, nevertheless probably what was provided might help.
Added: unique_multidimensional_array reimplementation
function unique_multidimensional_array($array, $key) {
$valuesByKey = [];
foreach($array as $value) {
$elementsByKey[$value[$key]] = $value;
}
return array_values($valuesByKey);
}

Related

search value in multi array [duplicate]

I have an array where I want to search the uid and get the key of the array.
Examples
Assume we have the following 2-dimensional array:
$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'
)
);
The function call search_by_uid(100) (uid of first user) should return 0.
The function call search_by_uid(40489) should return 2.
I tried making loops, but I want a faster executing code.
function searchForId($id, $array) {
foreach ($array as $key => $val) {
if ($val['uid'] === $id) {
return $key;
}
}
return null;
}
This will work. You should call it like this:
$id = searchForId('100', $userdb);
It is important to know that if you are using === operator compared types have to be exactly same, in this example you have to search string or just use == instead ===.
Based on angoru answer. In later versions of PHP (>= 5.5.0) you can use one-liner.
$key = array_search('100', array_column($userdb, 'uid'));
Here is documentation: http://php.net/manual/en/function.array-column.php.
If you are using (PHP 5 >= 5.5.0) you don't have to write your own function to do this, just write this line and it's done.
If you want just one result:
$key = array_search(40489, array_column($userdb, 'uid'));
For multiple results
$keys = array_keys(array_column($userdb, 'uid'), 40489);
In case you have an associative array as pointed in the comments you could make it with:
$keys = array_keys(array_combine(array_keys($userdb), array_column($userdb, 'uid')),40489);
If you are using PHP < 5.5.0, you can use this backport, thanks ramsey!
Update: I've been making some simple benchmarks and the multiple results form seems to be the fastest one, even faster than the Jakub custom function!
In later versions of PHP (>= 5.5.0) you can use this one-liner:
$key = array_search('100', array_column($userdb, 'uid'));
Building off Jakub's excellent answer, here is a more generalized search that will allow the key to specified (not just for uid):
function searcharray($value, $key, $array) {
foreach ($array as $k => $val) {
if ($val[$key] == $value) {
return $k;
}
}
return null;
}
Usage: $results = searcharray('searchvalue', searchkey, $array);
Looks array_filter will be suitable solution for this...
$userdb=Array
(
(0) => Array
(
(uid) => '100',
(name) => 'Sandra Shush',
(url) => 'urlof100'
),
(1) => Array
(
(uid) => '5465',
(name) => 'Stefanie Mcmohn',
(pic_square) => 'urlof100'
),
(2) => Array
(
(uid) => '40489',
(name) => 'Michael',
(pic_square) => 'urlof40489'
)
);
PHP Code
<?php
$search = 5465;
$found = array_filter($userdb,function($v,$k) use ($search){
return $v['uid'] == $search;
},ARRAY_FILTER_USE_BOTH); // With latest PHP third parameter is optional.. Available Values:- ARRAY_FILTER_USE_BOTH OR ARRAY_FILTER_USE_KEY
$values= print_r(array_values($found));
$keys = print_r(array_keys($found));
I know this was already answered, but I used this and extended it a little more in my code so that you didn't have search by only the uid. I just want to share it for anyone else who may need that functionality.
Here's my example and please bare in mind this is my first answer. I took out the param array because I only needed to search one specific array, but you could easily add it in. I wanted to essentially search by more than just the uid.
Also, in my situation there may be multiple keys to return as a result of searching by other fields that may not be unique.
/**
* #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;
}
Later, I ended up writing this to allow me to search for another value and associative key. So my first example allows you to search for a value in any specific associative key, and return all the matches.
This second example shows you where a value ('Taylor') is found in a certain associative key (first_name) AND another value (true) is found in another associative key (employed), and returns all matches (Keys where people with first name 'Taylor' AND are employed).
/**
* #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;
}
Use of function
$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);
Result
Array ( [0] => 2 )
You can do that with combination of two functions, array_search & array_column.
$search_value = '5465';
$search_key = 'uid';
$user = array_search($search_value, array_column($userdb, $search_key));
print_r($userdb[$user]);
5465 is the user ID you want to search, uid is the key that contains user ID and $userdb is the array that is defined in the question.
References:
array_search on php.net
array_column on php.net
I modified one of examples below description function array_search. Function searchItemsByKey return all value(s) by $key from multidimensional array ( N levels). Perhaps , it would be useful for somebody. Example:
$arr = array(
'XXX'=>array(
'YYY'=> array(
'AAA'=> array(
'keyN' =>'value1'
)
),
'ZZZ'=> array(
'BBB'=> array(
'keyN' => 'value2'
)
)
//.....
)
);
$result = searchItemsByKey($arr,'keyN');
print '<pre>';
print_r($result);
print '<pre>';
// OUTPUT
Array
(
[0] => value1
[1] => value2
)
Function code:
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;
}
Here is one liner for the same,
$pic_square = $userdb[array_search($uid,array_column($userdb, 'uid'))]['pic_square'];
Even though this is an old question and has an accepted answer, Thought i would suggest one change to the accepted answer.. So first off, i agree the accepted answer is correct here.
function searchArrayKeyVal($sKey, $id, $array) {
foreach ($array as $key => $val) {
if ($val[$sKey] == $id) {
return $key;
}
}
return false;
}
Replacing the preset 'uid' with a parameter in the function instead, so now calling the below code means you can use the one function across multiple array types. Small change, but one that makes the slight difference.
// 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";
}
PHP Fiddle Example
I want to check tha in the following array $arr is there 'abc' exists in sub arrays or not
$arr = array(
array(
'title' => 'abc'
)
);
Then i can use this
$res = array_search('abc', array_column($arr, 'title'));
if($res == ''){
echo 'exists';
} else {
echo 'notExists';
}
I think This is the Most simple way to define
I had to use un function which finds every elements in an array. So I modified the function done by Jakub Truneček as follow:
function search_in_array_r($needle, $array) {
$found = array();
foreach ($array as $key => $val) {
if ($val[1] == $needle) {
array_push($found, $val[1]);
}
}
if (count($found) != 0)
return $found;
else
return null;
}
/**
* 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;
}
you can use this function ;
https://github.com/serhatozles/ArrayAdvancedSearch
<?php
include('ArraySearch.php');
$query = "a='Example World' and b>='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 '<pre>';
print_r($Result);
echo '</pre>';
// Output:
// Array
// (
// [0] => Array
// (
// [a] => Example World
// [b] => 2
// )
//
// )
$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);
Try this
<?php
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) &&
recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
?>
Just share, maybe can like this.
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;
}}
No one else has used array_reduce yet, so thought I'd add this approach...
$find_by_uid = '100';
$is_in_array = array_reduce($userdb, function($carry, $user) use ($find_by_uid){
return $carry ? $carry : $user['uid'] === $find_by_uid;
});
// Returns true
Gives you more fine control over the 'search' logic than array_search().
Note that I have used strict equality here but you could opt for different comparison logic. The $carry means the comparison needs to be true once, and the final result will be TRUE.
I was looking for functionality similar to that of MySQL LIKE %term%. Based on the answers on this page. I am able to search the JSON array from a file.
user_list.json looks as sample below:
{
"user-23456": {
"name": "John Doe",
"age": "20",
"email": "doe#sample.com",
"user_id": "23456"
},
"user-09876": {
"name": "Ronojoy Adams",
"age": "35",
"email": "joy#sample.com",
"user_id": "09876"
},
"user-34890": {
"name": "Will Artkin",
"age": "16",
"email": "will#sample.com",
"user_id": "34890"
},
}
/*
*search_key_like
*/
function search_key_like($value, $key, $array) {
$results=array();
$keyword = preg_quote($value, '~');
foreach ($array as $k => $val) {
//if name a is spell John and keyword is sent as joh or JOH it will return null
//to fix the issue convert the string into lowercase and uppercase
$data=array($val[$key],strtolower($val[$key]),strtoupper($val[$key]));
if (preg_grep('~' . $keyword . '~', $data)) {
array_push($results,$val[$key]);
}
}
return $results;
}
Usage===pulling the JSON file===
$user_list_json='./user_list.json';
if(file_exists($user_list_json) && file_get_contents($user_list_json)){
$file_json_data=file_get_contents($user_list_json);
$json_array_data=json_decode($file_json_data,true);
$user_name_like = search_key_like('ron', 'name', $json_array_data);
print "<pre>".print_r($user_name_like,true);
}
for( $i =0; $i < sizeof($allUsers); $i++)
{
$NEEDLE1='firstname';
$NEEDLE2='emailAddress';
$sterm='Tofind';
if(isset($allUsers[$i][$NEEDLE1]) && isset($allUsers[$i][$NEEDLE2])
{
$Fname= $allUsers[$i][$NEEDLE1];
$Lname= $allUsers[$i][$NEEDLE2];
$pos1 = stripos($Fname, $sterm);
$pos2=stripos($Lname, $sterm);//not case sensitive
if($pos1 !== false ||$pos2 !== false)
{$resultsMatched[] =$allUsers[$i];}
else
{ continue;}
}
}
Print_r($resultsMatched); //will give array for matched values even partially matched
With help of above code one can find any(partially matched) data from any column in 2D array so user id can be found as required in question.
Expanding on the function #mayhem created, this example would be more of a "fuzzy" search in case you just want to match part (most) of a search string:
function searchArrayKeyVal($sKey, $id, $array) {
foreach ($array as $key => $val) {
if (strpos(strtolower($val[$sKey]), strtolower(trim($id))) !== false) {
return $key;
}
}
return false;
}
For example the value in the array is Welcome to New York! and you wanted the first instance of just "New York!"
If question i.e.
$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",
],
];
Ans:
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));
Here is a better solution, in case your pulling data from a database or a multidimensional array
Example of a multidimensional array:
$records = array(
array(
'id' => 2135,
'first_name' => 'John',
'last_name' => 'Doe',
),
array(
'id' => 3245,
'first_name' => 'Sally',
'last_name' => 'Smith',
),
array(
'id' => 5342,
'first_name' => 'Jane',
'last_name' => 'Jones',
),
array(
'id' => 5623,
'first_name' => 'Peter',
'last_name' => 'Doe',
)
);
function search_user_by_name($name, $array) {
foreach ($array as $keys) {
foreach ($keys as $key => $_user_record) {
if ($_user_record == $name) {
return [$key => $_user_record];//Return and array of user
}
}
}
return null;
}
Call the function:
$results = search_user_by_name('John', $records);
print_r($results);
Output: Array ( [first_name] => John )

PHP fastest way to serach an multiarray [duplicate]

I have an array where I want to search the uid and get the key of the array.
Examples
Assume we have the following 2-dimensional array:
$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'
)
);
The function call search_by_uid(100) (uid of first user) should return 0.
The function call search_by_uid(40489) should return 2.
I tried making loops, but I want a faster executing code.
function searchForId($id, $array) {
foreach ($array as $key => $val) {
if ($val['uid'] === $id) {
return $key;
}
}
return null;
}
This will work. You should call it like this:
$id = searchForId('100', $userdb);
It is important to know that if you are using === operator compared types have to be exactly same, in this example you have to search string or just use == instead ===.
Based on angoru answer. In later versions of PHP (>= 5.5.0) you can use one-liner.
$key = array_search('100', array_column($userdb, 'uid'));
Here is documentation: http://php.net/manual/en/function.array-column.php.
If you are using (PHP 5 >= 5.5.0) you don't have to write your own function to do this, just write this line and it's done.
If you want just one result:
$key = array_search(40489, array_column($userdb, 'uid'));
For multiple results
$keys = array_keys(array_column($userdb, 'uid'), 40489);
In case you have an associative array as pointed in the comments you could make it with:
$keys = array_keys(array_combine(array_keys($userdb), array_column($userdb, 'uid')),40489);
If you are using PHP < 5.5.0, you can use this backport, thanks ramsey!
Update: I've been making some simple benchmarks and the multiple results form seems to be the fastest one, even faster than the Jakub custom function!
In later versions of PHP (>= 5.5.0) you can use this one-liner:
$key = array_search('100', array_column($userdb, 'uid'));
Building off Jakub's excellent answer, here is a more generalized search that will allow the key to specified (not just for uid):
function searcharray($value, $key, $array) {
foreach ($array as $k => $val) {
if ($val[$key] == $value) {
return $k;
}
}
return null;
}
Usage: $results = searcharray('searchvalue', searchkey, $array);
Looks array_filter will be suitable solution for this...
$userdb=Array
(
(0) => Array
(
(uid) => '100',
(name) => 'Sandra Shush',
(url) => 'urlof100'
),
(1) => Array
(
(uid) => '5465',
(name) => 'Stefanie Mcmohn',
(pic_square) => 'urlof100'
),
(2) => Array
(
(uid) => '40489',
(name) => 'Michael',
(pic_square) => 'urlof40489'
)
);
PHP Code
<?php
$search = 5465;
$found = array_filter($userdb,function($v,$k) use ($search){
return $v['uid'] == $search;
},ARRAY_FILTER_USE_BOTH); // With latest PHP third parameter is optional.. Available Values:- ARRAY_FILTER_USE_BOTH OR ARRAY_FILTER_USE_KEY
$values= print_r(array_values($found));
$keys = print_r(array_keys($found));
I know this was already answered, but I used this and extended it a little more in my code so that you didn't have search by only the uid. I just want to share it for anyone else who may need that functionality.
Here's my example and please bare in mind this is my first answer. I took out the param array because I only needed to search one specific array, but you could easily add it in. I wanted to essentially search by more than just the uid.
Also, in my situation there may be multiple keys to return as a result of searching by other fields that may not be unique.
/**
* #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;
}
Later, I ended up writing this to allow me to search for another value and associative key. So my first example allows you to search for a value in any specific associative key, and return all the matches.
This second example shows you where a value ('Taylor') is found in a certain associative key (first_name) AND another value (true) is found in another associative key (employed), and returns all matches (Keys where people with first name 'Taylor' AND are employed).
/**
* #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;
}
Use of function
$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);
Result
Array ( [0] => 2 )
You can do that with combination of two functions, array_search & array_column.
$search_value = '5465';
$search_key = 'uid';
$user = array_search($search_value, array_column($userdb, $search_key));
print_r($userdb[$user]);
5465 is the user ID you want to search, uid is the key that contains user ID and $userdb is the array that is defined in the question.
References:
array_search on php.net
array_column on php.net
I modified one of examples below description function array_search. Function searchItemsByKey return all value(s) by $key from multidimensional array ( N levels). Perhaps , it would be useful for somebody. Example:
$arr = array(
'XXX'=>array(
'YYY'=> array(
'AAA'=> array(
'keyN' =>'value1'
)
),
'ZZZ'=> array(
'BBB'=> array(
'keyN' => 'value2'
)
)
//.....
)
);
$result = searchItemsByKey($arr,'keyN');
print '<pre>';
print_r($result);
print '<pre>';
// OUTPUT
Array
(
[0] => value1
[1] => value2
)
Function code:
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;
}
Here is one liner for the same,
$pic_square = $userdb[array_search($uid,array_column($userdb, 'uid'))]['pic_square'];
Even though this is an old question and has an accepted answer, Thought i would suggest one change to the accepted answer.. So first off, i agree the accepted answer is correct here.
function searchArrayKeyVal($sKey, $id, $array) {
foreach ($array as $key => $val) {
if ($val[$sKey] == $id) {
return $key;
}
}
return false;
}
Replacing the preset 'uid' with a parameter in the function instead, so now calling the below code means you can use the one function across multiple array types. Small change, but one that makes the slight difference.
// 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";
}
PHP Fiddle Example
I want to check tha in the following array $arr is there 'abc' exists in sub arrays or not
$arr = array(
array(
'title' => 'abc'
)
);
Then i can use this
$res = array_search('abc', array_column($arr, 'title'));
if($res == ''){
echo 'exists';
} else {
echo 'notExists';
}
I think This is the Most simple way to define
I had to use un function which finds every elements in an array. So I modified the function done by Jakub Truneček as follow:
function search_in_array_r($needle, $array) {
$found = array();
foreach ($array as $key => $val) {
if ($val[1] == $needle) {
array_push($found, $val[1]);
}
}
if (count($found) != 0)
return $found;
else
return null;
}
/**
* 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;
}
you can use this function ;
https://github.com/serhatozles/ArrayAdvancedSearch
<?php
include('ArraySearch.php');
$query = "a='Example World' and b>='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 '<pre>';
print_r($Result);
echo '</pre>';
// Output:
// Array
// (
// [0] => Array
// (
// [a] => Example World
// [b] => 2
// )
//
// )
$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);
Try this
<?php
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) &&
recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
?>
Just share, maybe can like this.
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;
}}
No one else has used array_reduce yet, so thought I'd add this approach...
$find_by_uid = '100';
$is_in_array = array_reduce($userdb, function($carry, $user) use ($find_by_uid){
return $carry ? $carry : $user['uid'] === $find_by_uid;
});
// Returns true
Gives you more fine control over the 'search' logic than array_search().
Note that I have used strict equality here but you could opt for different comparison logic. The $carry means the comparison needs to be true once, and the final result will be TRUE.
I was looking for functionality similar to that of MySQL LIKE %term%. Based on the answers on this page. I am able to search the JSON array from a file.
user_list.json looks as sample below:
{
"user-23456": {
"name": "John Doe",
"age": "20",
"email": "doe#sample.com",
"user_id": "23456"
},
"user-09876": {
"name": "Ronojoy Adams",
"age": "35",
"email": "joy#sample.com",
"user_id": "09876"
},
"user-34890": {
"name": "Will Artkin",
"age": "16",
"email": "will#sample.com",
"user_id": "34890"
},
}
/*
*search_key_like
*/
function search_key_like($value, $key, $array) {
$results=array();
$keyword = preg_quote($value, '~');
foreach ($array as $k => $val) {
//if name a is spell John and keyword is sent as joh or JOH it will return null
//to fix the issue convert the string into lowercase and uppercase
$data=array($val[$key],strtolower($val[$key]),strtoupper($val[$key]));
if (preg_grep('~' . $keyword . '~', $data)) {
array_push($results,$val[$key]);
}
}
return $results;
}
Usage===pulling the JSON file===
$user_list_json='./user_list.json';
if(file_exists($user_list_json) && file_get_contents($user_list_json)){
$file_json_data=file_get_contents($user_list_json);
$json_array_data=json_decode($file_json_data,true);
$user_name_like = search_key_like('ron', 'name', $json_array_data);
print "<pre>".print_r($user_name_like,true);
}
for( $i =0; $i < sizeof($allUsers); $i++)
{
$NEEDLE1='firstname';
$NEEDLE2='emailAddress';
$sterm='Tofind';
if(isset($allUsers[$i][$NEEDLE1]) && isset($allUsers[$i][$NEEDLE2])
{
$Fname= $allUsers[$i][$NEEDLE1];
$Lname= $allUsers[$i][$NEEDLE2];
$pos1 = stripos($Fname, $sterm);
$pos2=stripos($Lname, $sterm);//not case sensitive
if($pos1 !== false ||$pos2 !== false)
{$resultsMatched[] =$allUsers[$i];}
else
{ continue;}
}
}
Print_r($resultsMatched); //will give array for matched values even partially matched
With help of above code one can find any(partially matched) data from any column in 2D array so user id can be found as required in question.
Expanding on the function #mayhem created, this example would be more of a "fuzzy" search in case you just want to match part (most) of a search string:
function searchArrayKeyVal($sKey, $id, $array) {
foreach ($array as $key => $val) {
if (strpos(strtolower($val[$sKey]), strtolower(trim($id))) !== false) {
return $key;
}
}
return false;
}
For example the value in the array is Welcome to New York! and you wanted the first instance of just "New York!"
If question i.e.
$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",
],
];
Ans:
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));
Here is a better solution, in case your pulling data from a database or a multidimensional array
Example of a multidimensional array:
$records = array(
array(
'id' => 2135,
'first_name' => 'John',
'last_name' => 'Doe',
),
array(
'id' => 3245,
'first_name' => 'Sally',
'last_name' => 'Smith',
),
array(
'id' => 5342,
'first_name' => 'Jane',
'last_name' => 'Jones',
),
array(
'id' => 5623,
'first_name' => 'Peter',
'last_name' => 'Doe',
)
);
function search_user_by_name($name, $array) {
foreach ($array as $keys) {
foreach ($keys as $key => $_user_record) {
if ($_user_record == $name) {
return [$key => $_user_record];//Return and array of user
}
}
}
return null;
}
Call the function:
$results = search_user_by_name('John', $records);
print_r($results);
Output: Array ( [first_name] => John )

How to get a value with keyword ID in the same array hierarchy level with PHP [duplicate]

I have an array where I want to search the uid and get the key of the array.
Examples
Assume we have the following 2-dimensional array:
$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'
)
);
The function call search_by_uid(100) (uid of first user) should return 0.
The function call search_by_uid(40489) should return 2.
I tried making loops, but I want a faster executing code.
function searchForId($id, $array) {
foreach ($array as $key => $val) {
if ($val['uid'] === $id) {
return $key;
}
}
return null;
}
This will work. You should call it like this:
$id = searchForId('100', $userdb);
It is important to know that if you are using === operator compared types have to be exactly same, in this example you have to search string or just use == instead ===.
Based on angoru answer. In later versions of PHP (>= 5.5.0) you can use one-liner.
$key = array_search('100', array_column($userdb, 'uid'));
Here is documentation: http://php.net/manual/en/function.array-column.php.
If you are using (PHP 5 >= 5.5.0) you don't have to write your own function to do this, just write this line and it's done.
If you want just one result:
$key = array_search(40489, array_column($userdb, 'uid'));
For multiple results
$keys = array_keys(array_column($userdb, 'uid'), 40489);
In case you have an associative array as pointed in the comments you could make it with:
$keys = array_keys(array_combine(array_keys($userdb), array_column($userdb, 'uid')),40489);
If you are using PHP < 5.5.0, you can use this backport, thanks ramsey!
Update: I've been making some simple benchmarks and the multiple results form seems to be the fastest one, even faster than the Jakub custom function!
In later versions of PHP (>= 5.5.0) you can use this one-liner:
$key = array_search('100', array_column($userdb, 'uid'));
Building off Jakub's excellent answer, here is a more generalized search that will allow the key to specified (not just for uid):
function searcharray($value, $key, $array) {
foreach ($array as $k => $val) {
if ($val[$key] == $value) {
return $k;
}
}
return null;
}
Usage: $results = searcharray('searchvalue', searchkey, $array);
Looks array_filter will be suitable solution for this...
$userdb=Array
(
(0) => Array
(
(uid) => '100',
(name) => 'Sandra Shush',
(url) => 'urlof100'
),
(1) => Array
(
(uid) => '5465',
(name) => 'Stefanie Mcmohn',
(pic_square) => 'urlof100'
),
(2) => Array
(
(uid) => '40489',
(name) => 'Michael',
(pic_square) => 'urlof40489'
)
);
PHP Code
<?php
$search = 5465;
$found = array_filter($userdb,function($v,$k) use ($search){
return $v['uid'] == $search;
},ARRAY_FILTER_USE_BOTH); // With latest PHP third parameter is optional.. Available Values:- ARRAY_FILTER_USE_BOTH OR ARRAY_FILTER_USE_KEY
$values= print_r(array_values($found));
$keys = print_r(array_keys($found));
I know this was already answered, but I used this and extended it a little more in my code so that you didn't have search by only the uid. I just want to share it for anyone else who may need that functionality.
Here's my example and please bare in mind this is my first answer. I took out the param array because I only needed to search one specific array, but you could easily add it in. I wanted to essentially search by more than just the uid.
Also, in my situation there may be multiple keys to return as a result of searching by other fields that may not be unique.
/**
* #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;
}
Later, I ended up writing this to allow me to search for another value and associative key. So my first example allows you to search for a value in any specific associative key, and return all the matches.
This second example shows you where a value ('Taylor') is found in a certain associative key (first_name) AND another value (true) is found in another associative key (employed), and returns all matches (Keys where people with first name 'Taylor' AND are employed).
/**
* #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;
}
Use of function
$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);
Result
Array ( [0] => 2 )
You can do that with combination of two functions, array_search & array_column.
$search_value = '5465';
$search_key = 'uid';
$user = array_search($search_value, array_column($userdb, $search_key));
print_r($userdb[$user]);
5465 is the user ID you want to search, uid is the key that contains user ID and $userdb is the array that is defined in the question.
References:
array_search on php.net
array_column on php.net
I modified one of examples below description function array_search. Function searchItemsByKey return all value(s) by $key from multidimensional array ( N levels). Perhaps , it would be useful for somebody. Example:
$arr = array(
'XXX'=>array(
'YYY'=> array(
'AAA'=> array(
'keyN' =>'value1'
)
),
'ZZZ'=> array(
'BBB'=> array(
'keyN' => 'value2'
)
)
//.....
)
);
$result = searchItemsByKey($arr,'keyN');
print '<pre>';
print_r($result);
print '<pre>';
// OUTPUT
Array
(
[0] => value1
[1] => value2
)
Function code:
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;
}
Here is one liner for the same,
$pic_square = $userdb[array_search($uid,array_column($userdb, 'uid'))]['pic_square'];
Even though this is an old question and has an accepted answer, Thought i would suggest one change to the accepted answer.. So first off, i agree the accepted answer is correct here.
function searchArrayKeyVal($sKey, $id, $array) {
foreach ($array as $key => $val) {
if ($val[$sKey] == $id) {
return $key;
}
}
return false;
}
Replacing the preset 'uid' with a parameter in the function instead, so now calling the below code means you can use the one function across multiple array types. Small change, but one that makes the slight difference.
// 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";
}
PHP Fiddle Example
I want to check tha in the following array $arr is there 'abc' exists in sub arrays or not
$arr = array(
array(
'title' => 'abc'
)
);
Then i can use this
$res = array_search('abc', array_column($arr, 'title'));
if($res == ''){
echo 'exists';
} else {
echo 'notExists';
}
I think This is the Most simple way to define
I had to use un function which finds every elements in an array. So I modified the function done by Jakub Truneček as follow:
function search_in_array_r($needle, $array) {
$found = array();
foreach ($array as $key => $val) {
if ($val[1] == $needle) {
array_push($found, $val[1]);
}
}
if (count($found) != 0)
return $found;
else
return null;
}
/**
* 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;
}
you can use this function ;
https://github.com/serhatozles/ArrayAdvancedSearch
<?php
include('ArraySearch.php');
$query = "a='Example World' and b>='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 '<pre>';
print_r($Result);
echo '</pre>';
// Output:
// Array
// (
// [0] => Array
// (
// [a] => Example World
// [b] => 2
// )
//
// )
$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);
Try this
<?php
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) &&
recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
?>
Just share, maybe can like this.
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;
}}
No one else has used array_reduce yet, so thought I'd add this approach...
$find_by_uid = '100';
$is_in_array = array_reduce($userdb, function($carry, $user) use ($find_by_uid){
return $carry ? $carry : $user['uid'] === $find_by_uid;
});
// Returns true
Gives you more fine control over the 'search' logic than array_search().
Note that I have used strict equality here but you could opt for different comparison logic. The $carry means the comparison needs to be true once, and the final result will be TRUE.
I was looking for functionality similar to that of MySQL LIKE %term%. Based on the answers on this page. I am able to search the JSON array from a file.
user_list.json looks as sample below:
{
"user-23456": {
"name": "John Doe",
"age": "20",
"email": "doe#sample.com",
"user_id": "23456"
},
"user-09876": {
"name": "Ronojoy Adams",
"age": "35",
"email": "joy#sample.com",
"user_id": "09876"
},
"user-34890": {
"name": "Will Artkin",
"age": "16",
"email": "will#sample.com",
"user_id": "34890"
},
}
/*
*search_key_like
*/
function search_key_like($value, $key, $array) {
$results=array();
$keyword = preg_quote($value, '~');
foreach ($array as $k => $val) {
//if name a is spell John and keyword is sent as joh or JOH it will return null
//to fix the issue convert the string into lowercase and uppercase
$data=array($val[$key],strtolower($val[$key]),strtoupper($val[$key]));
if (preg_grep('~' . $keyword . '~', $data)) {
array_push($results,$val[$key]);
}
}
return $results;
}
Usage===pulling the JSON file===
$user_list_json='./user_list.json';
if(file_exists($user_list_json) && file_get_contents($user_list_json)){
$file_json_data=file_get_contents($user_list_json);
$json_array_data=json_decode($file_json_data,true);
$user_name_like = search_key_like('ron', 'name', $json_array_data);
print "<pre>".print_r($user_name_like,true);
}
for( $i =0; $i < sizeof($allUsers); $i++)
{
$NEEDLE1='firstname';
$NEEDLE2='emailAddress';
$sterm='Tofind';
if(isset($allUsers[$i][$NEEDLE1]) && isset($allUsers[$i][$NEEDLE2])
{
$Fname= $allUsers[$i][$NEEDLE1];
$Lname= $allUsers[$i][$NEEDLE2];
$pos1 = stripos($Fname, $sterm);
$pos2=stripos($Lname, $sterm);//not case sensitive
if($pos1 !== false ||$pos2 !== false)
{$resultsMatched[] =$allUsers[$i];}
else
{ continue;}
}
}
Print_r($resultsMatched); //will give array for matched values even partially matched
With help of above code one can find any(partially matched) data from any column in 2D array so user id can be found as required in question.
Expanding on the function #mayhem created, this example would be more of a "fuzzy" search in case you just want to match part (most) of a search string:
function searchArrayKeyVal($sKey, $id, $array) {
foreach ($array as $key => $val) {
if (strpos(strtolower($val[$sKey]), strtolower(trim($id))) !== false) {
return $key;
}
}
return false;
}
For example the value in the array is Welcome to New York! and you wanted the first instance of just "New York!"
If question i.e.
$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",
],
];
Ans:
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));
Here is a better solution, in case your pulling data from a database or a multidimensional array
Example of a multidimensional array:
$records = array(
array(
'id' => 2135,
'first_name' => 'John',
'last_name' => 'Doe',
),
array(
'id' => 3245,
'first_name' => 'Sally',
'last_name' => 'Smith',
),
array(
'id' => 5342,
'first_name' => 'Jane',
'last_name' => 'Jones',
),
array(
'id' => 5623,
'first_name' => 'Peter',
'last_name' => 'Doe',
)
);
function search_user_by_name($name, $array) {
foreach ($array as $keys) {
foreach ($keys as $key => $_user_record) {
if ($_user_record == $name) {
return [$key => $_user_record];//Return and array of user
}
}
}
return null;
}
Call the function:
$results = search_user_by_name('John', $records);
print_r($results);
Output: Array ( [first_name] => John )

Find key array / sub_array php [duplicate]

I have an array where I want to search the uid and get the key of the array.
Examples
Assume we have the following 2-dimensional array:
$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'
)
);
The function call search_by_uid(100) (uid of first user) should return 0.
The function call search_by_uid(40489) should return 2.
I tried making loops, but I want a faster executing code.
function searchForId($id, $array) {
foreach ($array as $key => $val) {
if ($val['uid'] === $id) {
return $key;
}
}
return null;
}
This will work. You should call it like this:
$id = searchForId('100', $userdb);
It is important to know that if you are using === operator compared types have to be exactly same, in this example you have to search string or just use == instead ===.
Based on angoru answer. In later versions of PHP (>= 5.5.0) you can use one-liner.
$key = array_search('100', array_column($userdb, 'uid'));
Here is documentation: http://php.net/manual/en/function.array-column.php.
If you are using (PHP 5 >= 5.5.0) you don't have to write your own function to do this, just write this line and it's done.
If you want just one result:
$key = array_search(40489, array_column($userdb, 'uid'));
For multiple results
$keys = array_keys(array_column($userdb, 'uid'), 40489);
In case you have an associative array as pointed in the comments you could make it with:
$keys = array_keys(array_combine(array_keys($userdb), array_column($userdb, 'uid')),40489);
If you are using PHP < 5.5.0, you can use this backport, thanks ramsey!
Update: I've been making some simple benchmarks and the multiple results form seems to be the fastest one, even faster than the Jakub custom function!
In later versions of PHP (>= 5.5.0) you can use this one-liner:
$key = array_search('100', array_column($userdb, 'uid'));
Building off Jakub's excellent answer, here is a more generalized search that will allow the key to specified (not just for uid):
function searcharray($value, $key, $array) {
foreach ($array as $k => $val) {
if ($val[$key] == $value) {
return $k;
}
}
return null;
}
Usage: $results = searcharray('searchvalue', searchkey, $array);
Looks array_filter will be suitable solution for this...
$userdb=Array
(
(0) => Array
(
(uid) => '100',
(name) => 'Sandra Shush',
(url) => 'urlof100'
),
(1) => Array
(
(uid) => '5465',
(name) => 'Stefanie Mcmohn',
(pic_square) => 'urlof100'
),
(2) => Array
(
(uid) => '40489',
(name) => 'Michael',
(pic_square) => 'urlof40489'
)
);
PHP Code
<?php
$search = 5465;
$found = array_filter($userdb,function($v,$k) use ($search){
return $v['uid'] == $search;
},ARRAY_FILTER_USE_BOTH); // With latest PHP third parameter is optional.. Available Values:- ARRAY_FILTER_USE_BOTH OR ARRAY_FILTER_USE_KEY
$values= print_r(array_values($found));
$keys = print_r(array_keys($found));
I know this was already answered, but I used this and extended it a little more in my code so that you didn't have search by only the uid. I just want to share it for anyone else who may need that functionality.
Here's my example and please bare in mind this is my first answer. I took out the param array because I only needed to search one specific array, but you could easily add it in. I wanted to essentially search by more than just the uid.
Also, in my situation there may be multiple keys to return as a result of searching by other fields that may not be unique.
/**
* #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;
}
Later, I ended up writing this to allow me to search for another value and associative key. So my first example allows you to search for a value in any specific associative key, and return all the matches.
This second example shows you where a value ('Taylor') is found in a certain associative key (first_name) AND another value (true) is found in another associative key (employed), and returns all matches (Keys where people with first name 'Taylor' AND are employed).
/**
* #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;
}
Use of function
$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);
Result
Array ( [0] => 2 )
You can do that with combination of two functions, array_search & array_column.
$search_value = '5465';
$search_key = 'uid';
$user = array_search($search_value, array_column($userdb, $search_key));
print_r($userdb[$user]);
5465 is the user ID you want to search, uid is the key that contains user ID and $userdb is the array that is defined in the question.
References:
array_search on php.net
array_column on php.net
I modified one of examples below description function array_search. Function searchItemsByKey return all value(s) by $key from multidimensional array ( N levels). Perhaps , it would be useful for somebody. Example:
$arr = array(
'XXX'=>array(
'YYY'=> array(
'AAA'=> array(
'keyN' =>'value1'
)
),
'ZZZ'=> array(
'BBB'=> array(
'keyN' => 'value2'
)
)
//.....
)
);
$result = searchItemsByKey($arr,'keyN');
print '<pre>';
print_r($result);
print '<pre>';
// OUTPUT
Array
(
[0] => value1
[1] => value2
)
Function code:
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;
}
Here is one liner for the same,
$pic_square = $userdb[array_search($uid,array_column($userdb, 'uid'))]['pic_square'];
Even though this is an old question and has an accepted answer, Thought i would suggest one change to the accepted answer.. So first off, i agree the accepted answer is correct here.
function searchArrayKeyVal($sKey, $id, $array) {
foreach ($array as $key => $val) {
if ($val[$sKey] == $id) {
return $key;
}
}
return false;
}
Replacing the preset 'uid' with a parameter in the function instead, so now calling the below code means you can use the one function across multiple array types. Small change, but one that makes the slight difference.
// 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";
}
PHP Fiddle Example
I want to check tha in the following array $arr is there 'abc' exists in sub arrays or not
$arr = array(
array(
'title' => 'abc'
)
);
Then i can use this
$res = array_search('abc', array_column($arr, 'title'));
if($res == ''){
echo 'exists';
} else {
echo 'notExists';
}
I think This is the Most simple way to define
I had to use un function which finds every elements in an array. So I modified the function done by Jakub Truneček as follow:
function search_in_array_r($needle, $array) {
$found = array();
foreach ($array as $key => $val) {
if ($val[1] == $needle) {
array_push($found, $val[1]);
}
}
if (count($found) != 0)
return $found;
else
return null;
}
/**
* 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;
}
you can use this function ;
https://github.com/serhatozles/ArrayAdvancedSearch
<?php
include('ArraySearch.php');
$query = "a='Example World' and b>='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 '<pre>';
print_r($Result);
echo '</pre>';
// Output:
// Array
// (
// [0] => Array
// (
// [a] => Example World
// [b] => 2
// )
//
// )
$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);
Try this
<?php
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) &&
recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
?>
Just share, maybe can like this.
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;
}}
No one else has used array_reduce yet, so thought I'd add this approach...
$find_by_uid = '100';
$is_in_array = array_reduce($userdb, function($carry, $user) use ($find_by_uid){
return $carry ? $carry : $user['uid'] === $find_by_uid;
});
// Returns true
Gives you more fine control over the 'search' logic than array_search().
Note that I have used strict equality here but you could opt for different comparison logic. The $carry means the comparison needs to be true once, and the final result will be TRUE.
I was looking for functionality similar to that of MySQL LIKE %term%. Based on the answers on this page. I am able to search the JSON array from a file.
user_list.json looks as sample below:
{
"user-23456": {
"name": "John Doe",
"age": "20",
"email": "doe#sample.com",
"user_id": "23456"
},
"user-09876": {
"name": "Ronojoy Adams",
"age": "35",
"email": "joy#sample.com",
"user_id": "09876"
},
"user-34890": {
"name": "Will Artkin",
"age": "16",
"email": "will#sample.com",
"user_id": "34890"
},
}
/*
*search_key_like
*/
function search_key_like($value, $key, $array) {
$results=array();
$keyword = preg_quote($value, '~');
foreach ($array as $k => $val) {
//if name a is spell John and keyword is sent as joh or JOH it will return null
//to fix the issue convert the string into lowercase and uppercase
$data=array($val[$key],strtolower($val[$key]),strtoupper($val[$key]));
if (preg_grep('~' . $keyword . '~', $data)) {
array_push($results,$val[$key]);
}
}
return $results;
}
Usage===pulling the JSON file===
$user_list_json='./user_list.json';
if(file_exists($user_list_json) && file_get_contents($user_list_json)){
$file_json_data=file_get_contents($user_list_json);
$json_array_data=json_decode($file_json_data,true);
$user_name_like = search_key_like('ron', 'name', $json_array_data);
print "<pre>".print_r($user_name_like,true);
}
for( $i =0; $i < sizeof($allUsers); $i++)
{
$NEEDLE1='firstname';
$NEEDLE2='emailAddress';
$sterm='Tofind';
if(isset($allUsers[$i][$NEEDLE1]) && isset($allUsers[$i][$NEEDLE2])
{
$Fname= $allUsers[$i][$NEEDLE1];
$Lname= $allUsers[$i][$NEEDLE2];
$pos1 = stripos($Fname, $sterm);
$pos2=stripos($Lname, $sterm);//not case sensitive
if($pos1 !== false ||$pos2 !== false)
{$resultsMatched[] =$allUsers[$i];}
else
{ continue;}
}
}
Print_r($resultsMatched); //will give array for matched values even partially matched
With help of above code one can find any(partially matched) data from any column in 2D array so user id can be found as required in question.
Expanding on the function #mayhem created, this example would be more of a "fuzzy" search in case you just want to match part (most) of a search string:
function searchArrayKeyVal($sKey, $id, $array) {
foreach ($array as $key => $val) {
if (strpos(strtolower($val[$sKey]), strtolower(trim($id))) !== false) {
return $key;
}
}
return false;
}
For example the value in the array is Welcome to New York! and you wanted the first instance of just "New York!"
If question i.e.
$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",
],
];
Ans:
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));
Here is a better solution, in case your pulling data from a database or a multidimensional array
Example of a multidimensional array:
$records = array(
array(
'id' => 2135,
'first_name' => 'John',
'last_name' => 'Doe',
),
array(
'id' => 3245,
'first_name' => 'Sally',
'last_name' => 'Smith',
),
array(
'id' => 5342,
'first_name' => 'Jane',
'last_name' => 'Jones',
),
array(
'id' => 5623,
'first_name' => 'Peter',
'last_name' => 'Doe',
)
);
function search_user_by_name($name, $array) {
foreach ($array as $keys) {
foreach ($keys as $key => $_user_record) {
if ($_user_record == $name) {
return [$key => $_user_record];//Return and array of user
}
}
}
return null;
}
Call the function:
$results = search_user_by_name('John', $records);
print_r($results);
Output: Array ( [first_name] => John )

PHP Multidimensional Array Searching (Find key by specific value)

I have this multidimensional array. I need to search it and return only the key that matches the value of the "slug". I know there are other threads about searching multidimensional arrays, but I'm not really understanding enough to apply to my situation. Thanks very much for any help!
So I need a function like:
myfunction($products,'breville-one-touch-tea-maker-BTM800XL');
// returns 1
Here's the Array:
$products = array (
1 => array(
'name' => 'The Breville One-Touch Tea Maker',
'slug' => 'breville-one-touch-tea-maker-BTM800XL',
'shortname' => 'The One-Touch Tea Maker',
'listprice' => '299.99',
'price' => '249.99',
'rating' => '9.5',
'reviews' => '81',
'buyurl' => 'http://www.amazon.com/The-Breville-One-Touch-Tea-Maker/dp/B003LNOPSG',
'videoref1' => 'xNb-FOTJY1c',
'videoref2' => 'WAyk-O2B6F8',
'image' => '812BpgHhjBML.jpg',
'related1' => '2',
'related2' => '3',
'related3' => '4',
'bestbuy' => '1',
'quote' => '',
'quoteautor' => 'K. Martino',
),
2 => array(
'name' => 'Breville Variable-Temperature Kettle BKE820XL',
'slug' => 'breville-variable-temperature-kettle-BKE820XL',
'shortname' => 'Variable Temperature Kettle',
'listprice' => '199.99',
'price' => '129.99',
'rating' => '9',
'reviews' => '78',
'buyurl' => 'http://www.amazon.com/Breville-BKE820XL-Variable-Temperature-1-8-Liter-Kettle/dp/B001DYERBK',
'videoref1' => 'oyZWBD83xeE',
'image' => '41y2B8jSKmwL.jpg',
'related1' => '3',
'related2' => '4',
'related3' => '5',
'bestbuy' => '1',
'quote' => '',
'quoteautor' => '',
),
);
Another poossible solution is based on the array_search() function. You need to use PHP 5.5.0 or higher.
Example
$userdb=Array
(
(0) => Array
(
(uid) => '100',
(name) => 'Sandra Shush',
(url) => 'urlof100'
),
(1) => Array
(
(uid) => '5465',
(name) => 'Stefanie Mcmohn',
(pic_square) => 'urlof100'
),
(2) => Array
(
(uid) => '40489',
(name) => 'Michael',
(pic_square) => 'urlof40489'
)
);
$key = array_search(40489, array_column($userdb, 'uid'));
echo ("The key is: ".$key);
//This will output- The key is: 2
Explanation
The function `array_search()` has two arguments. The first one is the value that you want to search. The second is where the function should search. The function `array_column()` gets the values of the elements which key is `'uid'`.
Summary
So you could use it as:
array_search('breville-one-touch-tea-maker-BTM800XL', array_column($products, 'slug'));
or, if you prefer:
// define function
function array_search_multidim($array, $column, $key){
return (array_search($key, array_column($array, $column)));
}
// use it
array_search_multidim($products, 'slug', 'breville-one-touch-tea-maker-BTM800XL');
The original example(by xfoxawy) can be found on the DOCS.
The array_column() page.
Update
Due to Vael comment I was curious, so I made a simple test to meassure the performance of the method that uses array_search and the method proposed on the accepted answer.
I created an array which contained 1000 arrays, the structure was like this (all data was randomized):
[
{
"_id": "57fe684fb22a07039b3f196c",
"index": 0,
"guid": "98dd3515-3f1e-4b89-8bb9-103b0d67e613",
"isActive": true,
"balance": "$2,372.04",
"picture": "http://placehold.it/32x32",
"age": 21,
"eyeColor": "blue",
"name": "Green",
"company": "MIXERS"
},...
]
I ran the search test 100 times searching for different values for the name field, and then I calculated the mean time in milliseconds. Here you can see an example.
Results were that the method proposed on this answer needed about 2E-7 to find the value, while the accepted answer method needed about 8E-7.
Like I said before both times are pretty aceptable for an application using an array with this size. If the size grows a lot, let's say 1M elements, then this little difference will be increased too.
Update II
I've added a test for the method based in array_walk_recursive which was mentionend on some of the answers here. The result got is the correct one. And if we focus on the performance, its a bit worse than the others examined on the test. In the test, you can see that is about 10 times slower than the method based on array_search. Again, this isn't a very relevant difference for the most of the applications.
Update III
Thanks to #mickmackusa for spotting several limitations on this method:
This method will fail on associative keys.
This method will only work on indexed subarrays (starting from 0 and have consecutively ascending keys).
Note on Update III
not taking performance into account: you can use array_combine with array_keys & array_column to overcome this limitation in a one-liner like:
$product_search_index =
array_search( 'breville-one-touch-tea-maker-BTM800XL', array_filter( array_combine( array_keys($products), array_column( $products, 'slug' ) ) ) );
Very simple:
function myfunction($products, $field, $value)
{
foreach($products as $key => $product)
{
if ( $product[$field] === $value )
return $key;
}
return false;
}
This class method can search in array by multiple conditions:
class Stdlib_Array
{
public static function multiSearch(array $array, array $pairs)
{
$found = array();
foreach ($array as $aKey => $aVal) {
$coincidences = 0;
foreach ($pairs as $pKey => $pVal) {
if (array_key_exists($pKey, $aVal) && $aVal[$pKey] == $pVal) {
$coincidences++;
}
}
if ($coincidences == count($pairs)) {
$found[$aKey] = $aVal;
}
}
return $found;
}
}
// Example:
$data = array(
array('foo' => 'test4', 'bar' => 'baz'),
array('foo' => 'test', 'bar' => 'baz'),
array('foo' => 'test1', 'bar' => 'baz3'),
array('foo' => 'test', 'bar' => 'baz'),
array('foo' => 'test', 'bar' => 'baz4'),
array('foo' => 'test4', 'bar' => 'baz1'),
array('foo' => 'test', 'bar' => 'baz1'),
array('foo' => 'test3', 'bar' => 'baz2'),
array('foo' => 'test', 'bar' => 'baz'),
array('foo' => 'test', 'bar' => 'baz'),
array('foo' => 'test4', 'bar' => 'baz1')
);
$result = Stdlib_Array::multiSearch($data, array('foo' => 'test4', 'bar' => 'baz1'));
var_dump($result);
Will produce:
array(2) {
[5]=>
array(2) {
["foo"]=>
string(5) "test4"
["bar"]=>
string(4) "baz1"
}
[10]=>
array(2) {
["foo"]=>
string(5) "test4"
["bar"]=>
string(4) "baz1"
}
}
Use this function:
function searchThroughArray($search,array $lists){
try{
foreach ($lists as $key => $value) {
if(is_array($value)){
array_walk_recursive($value, function($v, $k) use($search ,$key,$value,&$val){
if(strpos($v, $search) !== false ) $val[$key]=$value;
});
}else{
if(strpos($value, $search) !== false ) $val[$key]=$value;
}
}
return $val;
}catch (Exception $e) {
return false;
}
}
and call function.
print_r(searchThroughArray('breville-one-touch-tea-maker-BTM800XL',$products));
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;
}
I would do like below, where $products is the actual array given in the problem at the very beginning.
print_r(
array_search("breville-variable-temperature-kettle-BKE820XL",
array_map(function($product){return $product["slug"];},$products))
);
Try this
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle==$value['uid'] OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
For the next visitor coming along: use the recursive array walk; it visits every "leaf" in the multidimensional array. Here's for inspiration:
function getMDArrayValueByKey($a, $k) {
$r = [];
array_walk_recursive ($a,
function ($item, $key) use ($k, &$r) {if ($key == $k) $r[] = $item;}
);
return $r;
}
You can convert the array to JSON and search as a string then return the found object, so no matter how deeply nested it'll find it quickly:
function findObjectByKeyValue($array, $key, $value){
$object = [];
$string = json_encode($array);
$foundPosition = strpos($string, '"' . $key . '":"' . $value . '"');
if( $foundPosition ){
$prevBracketPos = strrpos(substr($string, 0, $foundPosition), '{');
if( $prevBracketPos ){
$nextBracketPos = strpos($string, '}', $foundPosition);
if( $nextBracketPos ){
$brackets = 0;
while( strpos(substr($string, $foundPosition, $nextBracketPos - $foundPosition), '{') &&
substr_count(substr($string, $foundPosition, $nextBracketPos - $foundPosition), '{') > $brackets
){
$lenToAdd = strlen(substr($string, $foundPosition, $nextBracketPos - $foundPosition + 1));
$nextBracketPos = strpos($string, '}', $foundPosition + $lenToAdd);
$brackets++;
}
$substr = substr($string, $prevBracketPos, $nextBracketPos - $prevBracketPos + 1);
// Confirm it's wrapped with brackets before we decode
if( substr($substr, 0, 1) === '{' && substr($substr, -1, 1) === '}' ){
$object = json_decode($substr, true);
}
}
}
}
return $object;
}
Example:
$arr = [{
"items":
{
"1": [
{
"id": "621eaf06062cd",
"nestedItem":
{
"id": "123",
"nestedItem":
{
"id": "456",
"nestedItem":
{
"id": "789"
}
}
}
}],
"2": [
{
"id": "621eb58de7364",
}],
"3": [
{
"id": "62226910716af",
}]
}
}];
echo findObjectByKeyValue($arr, 'id', '123');
/* {
"id": "123",
"nestedItem":
{
"id": "456",
"nestedItem":
{
"id": "789"
}
}
} /*
echo findObjectByKeyValue($arr, 'id', '621eaf06062cd');
/* {
"id": "621eaf06062cd",
"nestedItem":
{
"id": "123",
"nestedItem":
{
"id": "456",
"nestedItem":
{
"id": "789"
}
}
}
} */
The only problem уоu could run into is if there're brackets within as strings in the array.
Works well on associative array :
public function getKeyByParamValue(string $param, mixed $value, array $array): mixed
{
$keys = $this->getKeysByParamValue($param, $value, $array);
return empty($keys) ? null : $keys[0];
}
public function getKeysByParamValue(string $param, mixed $value, array $array): ?array
{
return array_keys(
array_combine(
array_keys($array),
array_column($array, $param)
),
$value
);
}

Categories