Asked  2 Years ago    Answers:  5   Viewed   129 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

2

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).

Friday, October 7, 2022
4

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";
}
Monday, December 19, 2022
 
2

I think you are looking for this:

function getIndex($name, $array){
    foreach($array as $key => $value){
        if(is_array($value) && $value['name'] == $name)
              return $key;
    }
    return null;
}
Tuesday, October 4, 2022
 
another
 
4

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*/}
Friday, September 16, 2022
 
1

The following should work:

Dim Numbers As Integer()() = {({1}), ({2}), ({3}), ({4, 5, 6, 7})}

As documents in Arrays in Visual Basic:

You can avoid an error when you supply nested array literals of different dimensions by enclosing the inner array literals in parentheses. The parentheses force the array literal expression to be evaluated, and the resulting values are used with the outer array literal

Sunday, October 23, 2022
 
markv
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 

Browse Other Code Languages