1

I have a hierarchical array in my project like this:

$Array = array(
    array(
        'Id' => 1,
        'Title' => 'Some Text1',
        'Children' => array(
            array(
                'Id' => 11,
                'Title' => 'Some Text11',
                'Children' => array(
                    array(
                        'Id' => 111,
                        'Title' => 'Some Text111',
                    ),
                    array(
                        'Id' => 112,
                        'Title' => 'Some Text112',
                        'Children' => array(
                            array(
                                'Id' => 1121,
                                'Title' => 'Some Text1121',
                            )
                        )
                    )
                )
            ),
            array(
                'Id' => 12,
                'Title' => 'Some Text12',
                'Children' => array(
                    array(
                        'Id' => 121,
                        'Title' => 'Some Text121',
                    )
                )
            )
        )
    ),
    array(
        'Id' => 2,
        'Title' => 'Some Text2',
    )
);

I want to search Title columns with a passed in string (such as Some Text1121) and return its path composed of Id values.

If the search is for Some Text1121, I want to return:

1 -> 11 -> 112 -> 1121

Or when I Search 'Some' string, return all Id paths in array.

3
  • Do you want exact match or list of similar? Please share if you tried anything? Commented Apr 28, 2018 at 8:35
  • You need recursive function for do that. Commented Apr 28, 2018 at 8:40
  • That's not a task that can be solved with a simple built in function. A custom recursive function will be involved. But it's on you to start somewhere.. Commented Apr 28, 2018 at 8:40

2 Answers 2

2

I've quickly written you something. It's not perfect, but you get the idea:

<?php

function searchRec($haystack, $needle, $pathId = Array(), $pathIndex = Array()) {
    foreach($haystack as $index => $item) {
        // add the current path to pathId-array
        $pathId[] = $item['Id'];
        // add the current index to pathIndex-array
        $pathIndex[] = $index;
        // check if we have a match
        if($item['Title'] == $needle) {
            // return the match
            $returnObject = new stdClass();
            // the current item where we have the match
            $returnObject->match = $item;   
            // path of Id's (1, 11, 112, 1121)
            $returnObject->pathId = $pathId; 
            // path of indexes (0,0,1,..) - you might need this to access the item directly
            $returnObject->pathIndex = $pathIndex; 
            return $returnObject;
        }

        if(isset($item['Children']) && count($item['Children']>0)) {
            // if this item has children, we call the same function (recursively) 
            // again to search inside those children:
            $result = searchRec($item['Children'], $needle, $pathId, $pathIndex);
            if($result) {
                // if that search was successful, return the match-object
                return $result;
            }
        }
    }
    return false;
}

// useage:
$result = searchRec($Array, "Some Text11");
var_dump($result);

// use 
echo implode(" -> ", $result->pathId);
// to get your desired 1 -> 11 -> 112

EDIT: rewritten to make the function actually return something. It now returns an Object with the matching item, the path of Id's and the path of (array-) Indexes.

Sign up to request clarification or add additional context in comments.

Comments

0

To search for partial matches on any level in your hierarchical array, use a recursive approach and search for qualifying substrings. When matches are found push the accumulated key path into the result array which is returned to the calling script.

This script will return an array of zero or more id-paths to qualifying titles. Demo

function pathFinder(array $array, string $find, string $path = ''): array {
    $paths = [];
    foreach ($array as $item) {
        $currentPath = $path . ($path ? ' -> ' : '') . $item['Id'];

        if (str_contains($item['Title'], $find)) {
            $paths[] = $currentPath;
        }

        if (isset($item['Children'])) {
            array_push(
                $paths,
                ...pathFinder($item['Children'], $find, $currentPath)
            );
        }
    }
    return $paths;
}
var_export(
    pathFinder($array, 'Some Text111')
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.