Filter Values from an Array Similar to SQL Like '%Search%' Using PHP

filter values from an array similar to SQL LIKE '%search%' using PHP

You don't need to use array_filter and a custom / lambda function, preg_grep does the trick:

$input = preg_quote('bl', '~'); // don't forget to quote input string!
$data = array('orange', 'blue', 'green', 'red', 'pink', 'brown', 'black');

$result = preg_grep('~' . $input . '~', $data);

Filter array elements by searching for partial match in keys and values

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(
'mark@test.by.com'=> "Mark Mian lv",
'jhon@test.lv.com'=> "John jack lv",
'logon@test.en.com'=> "Bob Logon",
'Stela@test.es.com'=> "Stela Josh",
'json@test.es.com'=> "Json Josh",
'bobby@test.lv.com'=> "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:

[jhon@test.lv.com] => John jack lv
[bobby@test.lv.com] => Bob Mark
[mark@test.by.com] => Mark Mian lv

Multidimensional array filter similar to mysql LIKE

use array_filter

function filterfunction($value) 
{

if(strcmp($value['country'],"UK")!=0
return false;
if(strcmp(substr($value['company'],0,2),"ht")==0)
return true;
return false;
}

$filterarr = array_filter($database, "filterfunction");

search php multidimensional associative array using key value pair with sql like '%LIKE%' construct

I think the way to go is with preg_match():

function match($search, $subject)
{
$search = str_replace('/', '\\/', $search);

return preg_match("/$search/i", (string)$subject);
}

function like_search_r($array, $key, $value, array &$results = [])
{
if (!is_array($array)) {
return;
}

$key = (string)$key;
$value = (string)$value;

foreach ($array as $arrayKey => $arrayValue) {
if (match($key, $arrayKey) && match($value, $arrayValue)) {
// add array if we have a match
$results[] = $array;
}

if (is_array($arrayValue)) {
// only do recursion on arrays
like_search_r($arrayValue, $key, $value, $results);
}
}
}

$array1 = [
'foo' => 'bar',
'subarr' => [
'test' => 'val',
'dangerous/characters' => 1,
],
];

$results1 = [];
like_search_r($array1, 'fo', 'bar', $results1);
print_r($results1);

/*
Array
(
[0] => Array
(
[foo] => bar
[subarr] => Array
(
[test] => val
[dangerous/characters] => 1
)

)

)
*/

$results2 = [];
like_search_r($array1, 'est', 'val', $results2);
print_r($results2);

/*
Array
(
[0] => Array
(
[test] => val
[dangerous/characters] => 1
)

)
*/

$results3 = [];
like_search_r($array1, 's/c', 1, $results3);
print_r($results3);

/*
Array
(
[0] => Array
(
[test] => val
[dangerous/characters] => 1
)

)
*/

Adjusted after your comment:

function match($search, $subject) { /* no change */ }

function like_search_r($array, $key, $value, array &$results = [], $level = 0)
{
if (!is_array($array)) {
return false;
}

$key = (string)$key;
$value = (string)$value;

$found = false;

foreach ($array as $arrayKey => $arrayValue) {
if (match($key, $arrayKey) && match($value, $arrayValue)) {
return true;
}

if (is_array($arrayValue)) {
// only do recursion on arrays
// results are only added on top level
if (like_search_r($arrayValue, $key, $value, $results, $level+1)) {
if ($level == 1) {
$results[] = $array;
}
$found = true;
}
}
}

return $found;
}

$array2 = [['id' => 0, 'values' => ['name' => 'bill']], ['id' => 1, 'values' => ['name' => 'john']]];
$results4 = [];
like_search_r($array2, 'name', 'john', $results4);
print_r($results4);

/*
Array
(
[0] => Array
(
[id] => 1
[values] => Array
(
[name] => john
)

)

)
*/

How to filter a two dimensional array by value

Use PHP's array_filter function with a callback.

$new = array_filter($arr, function ($var) {
return ($var['name'] == 'CarEnquiry');
});

Edit: If it needs to be interchangeable, you can modify the code slightly:

$filterBy = 'CarEnquiry'; // or Finance etc.

$new = array_filter($arr, function ($var) use ($filterBy) {
return ($var['name'] == $filterBy);
});

search a php array for partial string match

You can use preg_grep function of php. It's supported in PHP >= 4.0.5.

$array = array(0 => 'blue', 1 => 'red', 2 => 'green string', 3 => 'red');
$m_array = preg_grep('/^green\s.*/', $array);

$m_array contains matched elements of array.

how to filter array where a key's value matches in php

Based on new information, this is what you likely want:

$arr = $wpdb->get_results("
SELECT GROUP_CONCAT(sy.year) as years,
sm.model_id as model_id,
sm.sub_name as sub_name
FROM `subyears` sy
JOIN `submodels` sm
ON sy.submodel_id=sm.id
GROUP BY sm.model_id
ORDER BY sm.model_id
");

The "years" column in the returned array will contain all of the years. By default, they are comma separated.

---OLD ANSWER BELOW---

You should do this in the query itself:

$arr = $wpdb->get_results("
SELECT sy.id, sy.year, sm.id, sm.model_id, sm.sub_name
FROM `subyears` sy
JOIN `submodels` sm
ON sy.submodel_id=sm.id
ORDER BY sm.model_id
");

If you really insist on doing it outside the query, you need to create an entirely new array:

$arr = array();
foreach($arr_years as $year)
foreach($arr_submodels as $submodel)
if($year->submodel_id == $submodel->id)
$arr[] = (object) array_merge((array) $year, (array) $submodel));

Now, $arr contains all the objects from the two arrays merged together where submodel_id == id. You can loop through $arr and do what you want.

I used array_merge because I don't know of any function to merge objects. If there is one, it will be more efficient.

Exact value search with PHP

Currently you concat all your columns to a single string and then search for an occurance of your search string anywhere in this concatenated string.

What you might actually want is to match each column exactly against your search string and return every row, which has an exact match in any column. To do an exact match, don't use LIKE. A simple = is what you want. To combine them, simply use the OR operator.

$query = "SELECT * FROM tbstats WHERE
date = '" . $valueToSearch . "' OR
mode = '" . $valueToSearch . "' OR
svar = '" . $valueToSearch . "' OR
sdev = '" . $valueToSearch . "'";

On top of that, you should realy escape your input or even better, use prepared statements.



Related Topics



Leave a reply



Submit