Check if array value exists in multidimensional array - php

I read this question and it answered part of my question, but no matter what I do to modify the function, I'm not getting the expected results.
I want to pass an array to this function and check if a value of this array, exists in the multidimensional array. How can I modify this function to work if $needle is an array?
//example data
$needle = array(
[0] => someemail#example.com,
[1] => anotheremail#example.com,
[2] => foo#bar.com
)
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
EDIT
After reading the answer supplied by TiMESPLiNTER I updated my function as follows and it works perfectly.
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (is_array($needle) && is_array($item)) {
if(array_intersect($needle,$item)) {
return true;
}
}
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}

Check if array_intersect() returns an array with at least one element. If yes one of your values in the $needle array is contained in the $haystack array.
I ended up with this function:
function in_array_r($needle, $haystack) {
$flatArray = array();
array_walk_recursive($haystack, function($val, $key) use (&$flatArray) {
$flatArray[] = $val;
});
return (count(array_intersect($needle, $flatArray)) > 0);
}
You may extend this function to accept multidimensional arrays for both $needle and $haystack.

Related

Search inside multidimensional array and return other key value

I have the following
Multidimensional array.
What I'm trying to do is to search for an IDITEM value and if it's found, return the value of the "PRECO" key.
I'm using the following function to check if the value exists and it works fine, but I can't find a way to get the "PRECO" value of the found IDITEM.
Function:
function search_array($needle, $haystack) {
if(in_array($needle, $haystack)) {
return true;
}
foreach($haystack as $element) {
if(is_array($element) && search_array($needle, $element))
return true;
}
return false;
}
Anyone can help me with that?
You can change the first if statement to return it instead of returning a boolean :
function search_array($needle, $haystack) {
if(in_array($needle, $haystack) && array_key_exists('PRECO', $haystack)) {
return $haystack['PRECO'];
}
foreach($haystack as $element) {
if(is_array($element))
{
$result = search_array($needle, $element);
if($result !== false)
return $result;
}
}
return false;
}
The easiest idea I can remember is converting that boolean search_array into a path creator, where it will return the path for the item, or false if it isn't found.
function get_array_path_to_needle($needle, array $haystack)
{
if(in_array($needle, $haystack))
{
return true;
}
foreach($haystack as $key => $element)
{
if(is_array($element) && ($path = get_array_path_to_needle($needle, $element)) !== false)
{
return $path === true ? $key : $key . '.' . $path;
}
}
return false;
}
Then, since you already have the path, then rerun the array to fetch the item
function get_array_value_from_path(array $path, array $haystack)
{
$current = $haystack;
foreach($path as $key)
{
if(is_array($current) && array_key_exists($key, $current))
{
$current = $current[$key];
}
else
{
return false;
}
}
return $current;
}
This wont get you the PRECO, but it will return the item (array) where id found the value you searched for.
So a simple usage would be:
$path = get_array_path_to_needle('000000000000001650', $data);
$item = get_array_value_from_path(explode('.', $path), $data);
// here you have full array for that item found
print_r($item);
// here you have your price
print_r($item['PRECO']);
Use a static variable to remember the status between multiple function calls, and also to store the desired PRECO value. It makes the function remember the value of the given variable ($needle_value in this example) between multiple calls.
So your search_array() function should be like this:
function search_array($needle, $haystack){
static $needle_value = null;
if($needle_value != null){
return $needle_value;
}
foreach($haystack as $key => $value){
if(is_array($value)){
search_array($needle, $value);
}else if($needle == $value){
$needle_value = $haystack['PRECO'];
break;
}
}
return $needle_value;
}
This function will finally return $needle_value, which is your desired PRECO value from the haystack.
The simplest way is to use a foreach loop twice. Check for the key and store the result into an array for later use.
Based on your array, the below
$search = '000000000000001650';
foreach($array as $element){
foreach ($element['ITEM'] as $item){
if (isset($item['IDITEM']) and $item['IDITEM'] == $search){
$results[] = $item['PRECO'];
}
}
}
print_r($results);
Will output
Array
(
[0] => 375
)
Here is the simple example with array:
// your array with two indexes
$yourArr = array(
0=>array(
'IDDEPARTAMENTO'=>'0000000001',
'DESCRDEPT'=>'Área',
'ITEM'=>
array(
array(
'SETID'=>'RX',
'IDITEM'=>'000000000000001367',
'DESCRITEM'=>'PISTA TESTE DRIV',
'PRECO'=>'1338.78'),
array(
'SETID'=>'RX',
'IDITEM'=>'000000000000001925',
'DESCRITEM'=>'PISTA TESTE DRIV2',
'PRECO'=>'916'),
)
),
1=>array(
'IDDEPARTAMENTO'=>'0000000010',
'DESCRDEPT'=>'Merch',
'ITEM'=>
array(
array(
'SETID'=>'RX',
'IDITEM'=>'000000000000002036',
'DESCRITEM'=>'PISTA TESTE DRIV23',
'PRECO'=>'200.78'),
array(
'SETID'=>'RX',
'IDITEM'=>'000000000000001608',
'DESCRITEM'=>'PISTA CRACHÁ DRIV4',
'PRECO'=>'44341'),
)
));
// solution
$newArr = array();
foreach ($yourArr as $value) {
foreach ($value as $key => $innerVal) {
if($key == 'ITEM'){
foreach ($innerVal as $key_inner => $keyinner) {
if(!empty($keyinner['IDITEM'])){
$newArr[$keyinner['IDITEM']] = $keyinner['PRECO'];
}
}
}
}
}
echo "<pre>";
print_r($newArr);
Result values with IDITEM:
Array
(
[000000000000001367] => 1338.78
[000000000000001925] => 916
[000000000000002036] => 200.78
[000000000000001608] => 44341
)

in_array() for array of array

Is there a function like in_array() than can, check conntent inside array of arrays?
I tried:
$day_events = Array();
array_push($day_events,array('aa','bb','cc'));
array_push($day_events,array('aa','bc','cd'));
array_push($day_events,array('ac','bd','ce'));
echo '<br />';
echo in_array('aa',$day_events); // empty
echo '<br />';
foreach ($day_events as &$value) {
echo in_array('aa',$value); // 11
}
first in_array() which is the kind of function I am looking for (avoiding the loop) gave empty.
Use this function, as in_array doesn't natively support multi-dimensional arrays:
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
In this case you would you use it like this:
echo in_array_r('aa', $day_events) ? 'Found' : 'Not found';
It was taken from this answer: https://stackoverflow.com/a/4128377/2612112.
By the way it is not avoiding first one it is avoiding the last one which has 'ac'. So you get true from first two. Your code works but I am not sure if that is what you want.

PHP Search Multidimensional Array - Not Associative

I am trying to write a piece of code that searches one column of 2-D array values and returns the key when it finds it. Right now I have two functions, one to find a value and return a boolean true or false and another (not working) to return the key. I would like to merge the two in the sense of preserving the recursive nature of the finding function but returning a key. I cannot think how to do both in one function, but working key finder would be much appreciated.
Thanks
function in_array_r($needle, $haystack, $strict = true) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
function loopAndFind($array, $index, $search){
$returnArray = array();
foreach($array as $k=>$v){
if($v[$index] == $search){
$returnArray[] = $k;
}
}
return $returnArray;
}`
Sorry, I meant to add an example. For instance:
Array [0]{
[0]=hello
[1]=6
}
[1]
{
[0]=world
[1]=4
}
and I want to search the array by the [x][0] index to check each string of words for the search term. If found, it should give back the index/key in the main array like "world" returns 1
This works:
$array = array(array('hello', 6), array('world', 4));
$searchTerm = 'world';
foreach ($array as $childKey => $childArray) {
if ($childArray['0'] == $searchTerm) {
echo $childKey; //Your Result
}
}
You already have all you need in your first function. PHP does the rest:
$findings = array_map('in_array_r', $haystack);
$findings = array_filter($findings); # remove all not found
var_dump(array_keys($findings)); # the keys you look for

Search number in array

$record_record contains:
Array
(
[0] => Array
(
[id] => 252
[origin] => laptop.me.
)
[1] => Array
(
[id] => 255
[origin] => hello.me.
)
[2] => Array
(
[id] => 254
[origin] => intel.me.
)
)
I need to search if 255 is exist in the array. The code below didn't work.
if (in_array('255', $record_record, true)) {
echo "'255' found with strict check\n";
}
else {
echo "nope\n";
}
I had a feeling because it's a nested array the function will not work. Help me please?
You need to do something like this:
<?php
function id_exists ($array, $id, $strict = FALSE) {
// Loop outer array
foreach ($array as $inner) {
// Make sure id is set, and compare it to the search value
if (isset($inner['id']) && (($strict) ? $inner['id'] === $id : $inner['id'] == $id)) {
// We found it
return TRUE;
}
}
// We didn't find it
return FALSE;
}
if (id_exists($record_record, 255, true)) {
echo "'255' found with strict check\n";
} else {
echo "nope\n";
}
Do something like :
foreach($record_record as $sub_array){
if (in_array('255', $sub_array, true)) {
echo "'255' found with strict check\n";
}
else {
echo "nope\n";
}
}
You'll need a recursive function for that. From elusive:
function in_array_r($needle, $haystack, $strict = true) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
Or, if your array structure will never change, just write a simple loop:
function in_2dimensional_array($needle, $haystack, $strict = true){
foreach ($haystack as $item) {
if (in_array($needle, $haystack, true)) {
return true;
}
}
return false;
}
Hacky solution. Someone else will post a nice one using array_map or something similar.
function in_nested_array($val, $arr)
{
$matched = false;
foreach ($arr AS $ar)
{
if (in_array($val, $ar, true)
{
$matched = true;
break;
}
}
return $matched;
}
if (in_nested_array(255, $record_record))
{
// partay
}
<?php
foreach($record_record as $record) {
$key = array_search('255', $record);
if ($key) {
echo "'255' found with strict check\n";
}
}
?>

Search for a key in an array, recursively

private function find($needle, $haystack) {
foreach ($haystack as $name => $file) {
if ($needle == $name) {
return $file;
} else if(is_array($file)) { //is folder
return $this->find($needle, $file); //file is the new haystack
}
}
return "did not find";
}
Hey, this method searches for a specific key in an associative array and returns the value associated with it. There's some problem with the recursion. Any clue?
Maybe it's overkill, but it's funny to use RecursiveIterators :)
UPDATE: Maybe it was overkill with old versions of PHP, but with >=5.6 (specially with 7.0) I would totally use this without doubt.
function recursiveFind(array $haystack, $needle)
{
$iterator = new RecursiveArrayIterator($haystack);
$recursive = new RecursiveIteratorIterator(
$iterator,
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($recursive as $key => $value) {
if ($key === $needle) {
return $value;
}
}
}
UPDATE: Also, as of PHP 5.6, with generators you can easily iterate over all elements which pass the filter, not only the first one:
function recursiveFind(array $haystack, $needle)
{
$iterator = new RecursiveArrayIterator($haystack);
$recursive = new RecursiveIteratorIterator(
$iterator,
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($recursive as $key => $value) {
if ($key === $needle) {
yield $value;
}
}
}
// Usage
foreach (recursiveFind($haystack, $needle) as $value) {
// Use `$value` here
}
function array_search_key( $needle_key, $array ) {
foreach($array AS $key=>$value){
if($key == $needle_key) return $value;
if(is_array($value)){
if( ($result = array_search_key($needle_key,$value)) !== false)
return $result;
}
}
return false;
}
this will work !
you need to stop the recursive deep search, by return false and then check it in the function.
you can find more examples of functions (like using RecursiveArrayIterator and more) in this link :
http://php.net/manual/en/function.array-search.php
The answer provided by xPheRe was extremely helpful, but didn't quite solve the problem in my implementation. There are multiple nested associative arrays in our data structure, and there may be multiple occurrences of any given key.
In order to suit our purposes, I needed to implement a holder array that was updated while traversing the entire structure, instead of returning on the first match. The real work was provided by another poster, but I wanted to say thanks and share the final step that I had to cover.
public function recursiveFind(array $array, $needle)
{
$iterator = new RecursiveArrayIterator($array);
$recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
$aHitList = array();
foreach ($recursive as $key => $value) {
if ($key === $needle) {
array_push($aHitList, $value);
}
}
return $aHitList;
}
try this:
array_walk_recursive(
$arrayToFindKey,
function($value, $key, $matchingKey){
return (strcasecmp($key, $matchingKey) == 0)? true : false;
}
, 'matchingKeyValue'
);
The best solution above misses the case if the key is repeated and only returns the first value, here I get all the values in an array instead:
function recursiveFind(array $array, $needle) {
$iterator = new RecursiveArrayIterator($array);
$recursive = new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST);
$return = [];
foreach ($recursive as $key => $value) {
if ($key === $needle) {
$return[] = $value;
}
}
return $return;
}
I just been through a similar issue and here's what worked for me:
function searchArrayByKey($haystack, $needle, $i = 0) {
$result = array();
foreach($haystack as $key => $value) {
if (is_array($value)) {
$nextKey = searchArrayByKey($value, $needle);
if ($nextKey) {
return $nextKey;
}
}
if (is_array($value) && array_key_exists($needle, $value)) {
$result[$i++] = $value[$needle];
}
}
if (empty($result)) {
return false;
} else {
return $result;
}
}
This is going to return an array containing the value of all the matching keys it found in the multidimensional array. I tested this with arrays dinamically generated by an e-mail API. In the case of multiple matches, you just need to create a simple foreach loop to sort the array however you want.
I noticed the main mistake I was making was using if-ifelse conditions when I should be using if-if conditions. Any questions or criticism are very welcome, cheers!
I recently came across the same issue, when dealing with Yii2 query object.
The reason your function didn't work is that the return action doesn't work here. Just pass a reference parameter to store the value, and do whatever you want afterwards.
As you can see, this is a simple PHP function doesn't rely on any library. So I think its worth to mention with all the answer listed above.
function array_search_by_key_recursive($needle, array $haystack, &$return)
{
foreach ($haystack as $k => $v) {
if (is_array($v)) {
array_search_by_key_recursive($needle, $v, $return);
} else {
if($k === $needle){
$return = $v;
}
}
}
}
array_search_by_key_recursive($needle, array $haystack, $return);
print_r($return);

Categories