Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to search in PHP Array, similar to MySQL Like %var% search

is it possible to do searching in PHP array same we do in MySQL.

Eg: I have this array

array(
  '[email protected]'=> `Mark Mian`,
  '[email protected]'=> `John jack`,
  '[email protected]'=> `Bob Logon`,
  '[email protected]'=> `Stela Josh`,
  '[email protected]'=> `Json Josh`
  '[email protected]'=> `Bob Mark`
)

and I would to do this type of searching,

Eg: If I search Mark it should return me this

'[email protected]' => `Mark Mian

If I search Bob it should return me

'[email protected]'=> Bob Mark

'[email protected]'=> Bob Logon,

If I search only a it should return me those elements which contains a eg:

'[email protected]'=> Mark Mian,

'[email protected]'=> John jack,

'[email protected]'=> Stela Josh,

'[email protected]'=> Bob Mark

Note: Search should be by key or value

like image 515
Qazi Avatar asked Mar 18 '16 09:03

Qazi


4 Answers

$needle="bob";
$output=array();
foreach($array as $k=>$v)
{
   if(stristr($k,$needle) || stristr($v,$needle))
   $output[$k]=$v;
}
print_r($output);

Fiddle

That is if you want to search keys and values both, Remove the keys part if you just want to search values.

like image 109
Hanky Panky Avatar answered Oct 21 '22 03:10

Hanky Panky


Here is a preg_grep solution that should work more like a WHERE REGEXP 'PATTERN' in MySQL. I modified Daniel Klein's preg_grep_keys function to search for the pattern within array keys, and added an array_merge to it, which should work with the arrays with non-numeric keys. If the keys are numeric, just use a mere preg_grep solution (preg_grep('~Mark~i', $arr); to find all array elements having mark or Mark, etc.).

array_merge
Merges the elements of one or more arrays together so that the values of one are appended to the end of the previous one. It returns the resulting array. If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended.

function preg_grep_keys_values($pattern, $input, $flags = 0) {
    return array_merge(
      array_intersect_key($input, array_flip(preg_grep($pattern, array_keys($input), $flags))),
      preg_grep($pattern, $input, $flags)
   );
}

$a = array(
  '[email protected]'=> "Mark Mian lv",
  '[email protected]'=> "John jack lv",
  '[email protected]'=> "Bob Logon",
  '[email protected]'=> "Stela Josh",
  '[email protected]'=> "Json Josh",
  '[email protected]'=> "Bob Mark"
);

$r = preg_grep_keys_values('~lv~i', $a);
print_r($r);

See this IDEONE demo

The code above searches for lv (case-insensitively) in the keys first, then in the values, and then merges the results into 1 array. Thus, the results are:

[[email protected]] => John jack lv
[[email protected]] => Bob Mark
[[email protected]] => Mark Mian lv
like image 38
Wiktor Stribiżew Avatar answered Oct 21 '22 03:10

Wiktor Stribiżew


An easy approach would be to use array_filter

If you want regex's, this would work

$regex = '~test~';
$result = array_filter($data, function($item) use ($regex) {
    return preg_match($regex, $item);
});

Or just a simple contains search

$search = 'test';
$result = array_filter($data, function($item) use ($search) {
    return stristr($value, $search);
});

If you have to search for both - key and value, you could append the parameter ARRAY_FILTER_USE_BOTH to array_filter.

$search = 'test';
$result = array_filter($data, function($item, $key) use ($search) {
    return stristr($value, $search) || stristr($key, $search);
}, ARRAY_FILTER_USE_BOTH);

And finally, you could combine array_filter with preg_grep to search for both at once.

$search = '~bob~i';
$result = array_filter($data, function() use ($search) {
    return count(preg_grep($search, func_get_args()));
}, ARRAY_FILTER_USE_BOTH);
like image 4
Philipp Avatar answered Oct 21 '22 04:10

Philipp


You want to filter an array, use array_filter that is designed for.

If you only search literal strings, you don't need to use a regex:

$needle = 'bob';

$result = array_filter($data, function ($k, $v) use ($needle) {
    return stripos($k, $needle) !== false || stripos($v, $needle) !== false;
}, ARRAY_FILTER_USE_BOTH);

If you want to be able to filter with a regex:

$pattern = '~n.*e~i';

$result = array_filter($data, function ($k, $v) use ($pattern) {
    return !empty(preg_grep($pattern, [$k, $v]));
}, ARRAY_FILTER_USE_BOTH);
like image 2
Casimir et Hippolyte Avatar answered Oct 21 '22 03:10

Casimir et Hippolyte