1

This issue is related to following issue: Search multidimensional array in PHP and return keys

I have following array I would like to search for strings using e.g. regular expressions:

[390] => Array
(
    [0] => hammer
    [1] => Properties
    [2] => tools, hammer, properties
    [3] => 
    [4] => done
    [png] => Array
        (
            [0] => hammer_16x.png
            [1] => hammer_32x.png
        )

    [eps] => Array
        (
            [0] => hammer_16x.eps
            [1] => hammer_32x.eps
        )

    [ico] => Array
        (
            [0] => hammer.ico
        )

)

I would like to especially search these values:

 [0] => hammer
 [1] => Properties
 [2] => tools, hammer, properties
 [3] => 
 [4] => done

e.g. the user shall have the possibility to find this array key when searching for "ham", "tools", "amm" etc.

I tried to adapt the solution posted in the post above but did not manage it. I've also found a solution using array_map, but this did not enable me to explicitly search in a specific attribute (e.g. I would like to further on limit a search to the first index in the array, here [0] => hammer):

$result= array_map('unserialize', preg_filter('/'.$searchterm.'/', '$0', array_map('serialize', $array)));

Your ideas are welcome :) Thanks!

1
  • I find this question to be unclearly asked. Are you not actually interested in a recursive solution, but seeking to search ONLY the non-array elements of the row (not search png, eps, and ico elements)? You want to search with ham, tools, amm, but you only want the first match? [0] => 'hammer'? Commented Mar 25, 2024 at 1:12

2 Answers 2

1

You may use this recursive function of preg_grep:

function preg_grep_recursive( $pattern, $input, $flags = 0, &$output = array() )
{
    foreach($input as $key => $val) {
        if(is_array($val)) {
            preg_grep_recursive($pattern, $val, $flags, $output);   
        } else {
            $output[] = $val;
        }
    }

    return preg_grep($pattern, $output, $flags);
}
Sign up to request clarification or add additional context in comments.

Comments

0

Try the following solution. It doesn't use regular expressions, it use plain string search instead. However it allows some flexibility as you want.

function filter($array, $filter_elem) {
    return array_filter($array, function ($v) use($filter_elem) {
        return
            count(array_udiff_assoc($filter_elem, $v, function ($a, $b) {
                if (!is_string($a) || !is_string($b)) return $a == $b? 0 : 1;
                return stripos($b, $a) !== false || stripos($a, $b) !== false? 0 : 1;
            })) == 0;
    });
}

$array = array(
    '390' => array(
        '0' => 'hammer',
        '1' => 'Properties',
        '2' => 'tools, hammer, properties',
        '3' => false,
        '4' => 'done',
        'png' => array(
            '0' => 'hammer_16x.png',
            '1' => 'hammer_32x.png',
        ),
        'eps' => array(
            '0' => 'hammer_16x.eps',
            '1' => 'hammer_32x.eps',
        ),
        'ico' => array(
            '0' => 'hammer.ico',
        ),
    ),
);

$filter_elem = array(
    '1' => 'prop',
    '2' => 'hammer',
    '3' => false,
    '4' => 'done',
);

print_r(filter($array, $filter_elem));

2 Comments

The example works fine! I've still tried to combine it with reg ex - also searching whole google - but did not find a solution yet. Even using OR search seems not to work.
array_udiff_assoc() expects a 3-way comparison because it is not only filtering, it is sorting as well.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.