Asked  7 Months ago    Answers:  5   Viewed   64 times

Is there any fast way to get all subarrays where a key value pair was found in a multidimensional array? I can't say how deep the array will be.

Simple example array:

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

When I search for key=name and value="cat 1" the function should return:

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

I guess the function has to be recursive to get down to the deepest level.

 Answers

11

Code:

function search($array, $key, $value)
{
    $results = array();

    if (is_array($array)) {
        if (isset($array[$key]) && $array[$key] == $value) {
            $results[] = $array;
        }

        foreach ($array as $subarray) {
            $results = array_merge($results, search($subarray, $key, $value));
        }
    }

    return $results;
}

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

print_r(search($arr, 'name', 'cat 1'));

Output:

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

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

)

If efficiency is important you could write it so all the recursive calls store their results in the same temporary $results array rather than merging arrays together, like so:

function search($array, $key, $value)
{
    $results = array();
    search_r($array, $key, $value, $results);
    return $results;
}

function search_r($array, $key, $value, &$results)
{
    if (!is_array($array)) {
        return;
    }

    if (isset($array[$key]) && $array[$key] == $value) {
        $results[] = $array;
    }

    foreach ($array as $subarray) {
        search_r($subarray, $key, $value, $results);
    }
}

The key there is that search_r takes its fourth parameter by reference rather than by value; the ampersand & is crucial.

FYI: If you have an older version of PHP then you have to specify the pass-by-reference part in the call to search_r rather than in its declaration. That is, the last line becomes search_r($subarray, $key, $value, &$results).

Wednesday, March 31, 2021
 
etsous
answered 7 Months ago
82

I think (and you have confirmed) that you can represent your data as an XML structure. I this case, you can use XPath to find any branch in your data. Here is sample XML data inferred from your question:

<?xml version="1.0" encoding="utf-8" ?>
<stmt_echo>
    <subnodes>
        <exprs>
            <expr_constfetch>
                <subnodes>
                    <name>
                        <name>
                            <subnodes>
                                <parts>
                                    <part>true</part>
                                    <!-- more items -->
                                </parts>
                            </subnodes>
                        </name>
                    </name>
                </subnodes>
            </expr_constfetch>
            <!-- more items -->
        </exprs>
    </subnodes>
</stmt_echo>

And here is the PHP code to locate the node you mentioned:

$doc = new DOMDocument;
$doc->Load("test.xml");

$xpath = new DOMXPath($doc);
$nodes = $xpath->query("//subnodes/parts[part='true']");

foreach($nodes as $node) {
    dumpNodePath($node);
}

# Output
# /stmt_echo/subnodes/exprs/expr_constfetch/subnodes/name/name/subnodes/parts

function dumpNodePath($node) {
    $path = array($node->tagName);
    while ($node = $node->parentNode) {
        if ($node->nodeType != XML_DOCUMENT_NODE) {
            $path[] = $node->tagName;
        }
    }
    echo "/" . implode("/", array_reverse($path)) . "n";
}
Friday, May 28, 2021
 
max_
answered 5 Months ago
59

Can never avoid the loop :-)

function search($array, $searchString){
   foreach($array as $key=>$val){
        if(in_array($searchString, $val)) return true;
   }
   return false;
}

//use it like so:
if(search($array, '109.148.183.1')){/*do something*/}
Saturday, May 29, 2021
 
DaveRandom
answered 5 Months ago
20

if the chararray contains stringend or do not end with you can use these code, because strstr will brake on these ones:

#include <stdio.h>
int main()
{
    char c_to_search[5] = "asdf";

    char text[68] = "hello my name is  there is some other string behind it n asdf";

    int pos_search = 0;
    int pos_text = 0;
    int len_search = 4;
    int len_text = 67;
    for (pos_text = 0; pos_text < len_text - len_search;++pos_text)
    {
        if(text[pos_text] == c_to_search[pos_search])
        {
            ++pos_search;
            if(pos_search == len_search)
            {
                // match
                printf("match from %d to %dn",pos_text-len_search,pos_text);
                return;
            }
        }
        else
        {
           pos_text -=pos_search;
           pos_search = 0;
        }
    }
    // no match
    printf("no matchn");
   return 0;
}

http://ideone.com/2In3mr

Monday, September 13, 2021
 
Mike
answered 1 Month ago
86

Simply make a custom function like as

function check_diff($arr1, $arr2){
    $check = (is_array($arr1) && count($arr1)>0) ? true : false;
    $result = ($check) ? ((is_array($arr2) && count($arr2) > 0) ? $arr2 : array()) : array();
    if($check){
        foreach($arr1 as $key => $value){
            if(isset($result[$key])){
                $result[$key] = array_diff($value,$result[$key]);
            }else{
                $result[$key] = $value;
            }
        }
    }

    return $result;
}
$result['qtr_final'] = check_diff($a1['qtr_selected'],$a2['qtr_completed']);
print_r($result);
Friday, October 22, 2021
 
Ericson Willians
answered 2 Days ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :