49
$example = array('An example','Another example','Last example');

How can I do a loose search for the word "Last" in the above array?

echo array_search('Last example',$example);

The code above will only echo the value's key if the needle matches everything in the value exactly, which is what I don't want. I want something like this:

echo array_search('Last',$example);

And I want the value's key to echo if the value contains the word "Last".

UserIsCorrupt
  • 4,837
  • 15
  • 38
  • 41

7 Answers7

71

To find values that match your search criteria, you can use array_filter function:

$example = array('An example','Another example','Last example');
$searchword = 'last';
$matches = array_filter($example, function($var) use ($searchword) { return preg_match("/\b$searchword\b/i", $var); });

Now $matches array will contain only elements from your original array that contain word last (case-insensitive).

If you need to find keys of the values that match the criteria, then you need to loop over the array:

$example = array('An example','Another example','One Example','Last example');
$searchword = 'last';
$matches = array();
foreach($example as $k=>$v) {
    if(preg_match("/\b$searchword\b/i", $v)) {
        $matches[$k] = $v;
    }
}

Now array $matches contains key-value pairs from the original array where values contain (case- insensitive) word last.

Mordred
  • 3,734
  • 3
  • 36
  • 55
Aleks G
  • 56,435
  • 29
  • 168
  • 265
  • if you are not trying to find by a regex don't forget to add `preg_quote()` to `$searchword`. – rodrigoq Dec 11 '14 at 01:11
  • Actually, this gives a syntax error, unknown where and it does not work... when I comment this like $matches = array_filter($example, function($var) use ($searchword) { return preg_match("/\b$searchword\b/i", $var); }); the script continues to work, when i add it it breaks. – Lachezar Raychev Nov 08 '15 at 10:31
  • @LachezarRaychev What version of php are you using? It works in 5.4, 5.5 and 5.6. – Aleks G Nov 08 '15 at 16:52
  • 2
    Nothing technically wrong with this but I can't for the life of me understand why use regex here wouldn't `strpos()` work just as well and be faster? – But those new buttons though.. Oct 18 '16 at 00:33
  • @billynoah Yes, it would :) – Aleks G Oct 18 '16 at 10:51
  • Is it possible, that this is broken in PHP 7? I get the following error: "strpos() expects parameter 1 to be string, array given" so it seems $var is an array in my case. Am I correct, that I don't have to initialize $var anywhere else? – Picl Mar 27 '19 at 23:50
  • @Picl I didn't propose strpos solution. You clearly have a different issue - post it as a new question. – Aleks G Mar 28 '19 at 12:55
  • @Aleks G Sorry, my answer was meant to belong to the solution by xdazz. – Picl May 09 '19 at 18:26
  • Do not forget to `preg_quote()` the input string, otherwise if your input string contains characters with special meaning for regex, it will produce unpredictable results: `return preg_match("/\b".preg_quote($searchword)."\b/i", $var); ` – Bud Damyanov Aug 15 '19 at 13:00
  • @BudDamyanov `preg_quote()` does not have a default delimiter value -- it must be declared. – mickmackusa May 11 '21 at 10:04
24
function customSearch($keyword, $arrayToSearch){
    foreach($arrayToSearch as $key => $arrayItem){
        if( stristr( $arrayItem, $keyword ) ){
            return $key;
        }
    }
}
Wayne Whitty
  • 19,513
  • 7
  • 44
  • 66
  • 2
    @MarcioSimao This will only return the key of the first matching element, not the array of keys of all matches. – Aleks G Sep 24 '14 at 11:23
  • @AleksG, This is exactly what i was looking for. If i'm not mistaken, the question is about the same thing. The last user's phrase is "And **I want the value's key** to echo if the value contains the word "Last"" – Marcio Mazzucato Sep 24 '14 at 11:59
  • @MarcioSimao Possibly it solves the issue for you, however it's limited to a single match. If you have multiple values with word _last_ in them, you'll only find the first one with this code. – Aleks G Sep 24 '14 at 13:56
  • @AleksG, Thanks to advice! But in my case, i need to find the first key, so this code is more optimized and legible. – Marcio Mazzucato Sep 24 '14 at 17:34
  • The php manual states that `strstr()` and `stristr()` should not be used to check the existence of a substring -- for efficiency reasons. – mickmackusa May 11 '21 at 10:05
15
$input= array('An example','Another example','Last example');
$needle = 'Last';
$ret = array_keys(array_filter($input, function($var) use ($needle){
    return strpos($var, $needle) !== false;
}));

This will give you all the keys whose value contain the needle.

xdazz
  • 158,678
  • 38
  • 247
  • 274
3

It finds an element's key with first match:

echo key(preg_grep('/\b$searchword\b/i', $example));

And if you need all keys use foreach:

foreach (preg_grep('/\b$searchword\b/i', $example) as $key => $value) {
  echo $key;
}
kenorb
  • 155,785
  • 88
  • 678
  • 743
aDaemon
  • 131
  • 3
  • Or even array_keys(preg_grep('/\b$searchword\b/i', $example)). I needed the same functionality and was going to write a wrapper function as well but this is perfect. – MSpreij Sep 19 '16 at 08:47
  • When adding a variable into a pattern, we should see `preg_quote()`. – mickmackusa May 11 '21 at 10:07
0

I do not like regex because as far as I know, they are always slower than a normal string function. So my solution is:

function substr_in_array($needle, array $haystack)
{
    foreach($haystack as $value)
    {
        if(strpos($value, $needle) !== FALSE) return TRUE;
    }
    return FALSE;
}
wp78de
  • 18,207
  • 7
  • 43
  • 71
Dario
  • 39
  • 4
0

The answer that Aleks G has given is not accurate enough.

$example = array('An example','Another example','One Example','Last example');
$searchword = 'last';
$matches = array();
foreach($example as $k=>$v) {
    if(preg_match("/\b$searchword\b/i", $v)) {
        $matches[$k] = $v;
    }
}

The line

if(preg_match("/\b$searchword\b/i", $v)) {

should be replaced by these ones

$match_result = preg_match("/\b$searchword\b/i", $v);
if( $match_result!== false && $match_result === 1 ) {

Or more simply

if( preg_match("/\b$searchword\b/i", $v) === 1 ) {

In agreement with http://php.net/manual/en/function.preg-match.php

preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or FALSE if an error occurred.

  • When adding a variable into a pattern, we should see `preg_quote()`. `preg_match()` used as a filter in a loop is more elegantly expressed as `preg_grep()`. – mickmackusa May 11 '21 at 10:11
-1

I was also looking for a solution to OP's problem and I stumbled upon this question via Google. However, none of these answers did it for me so I came up with something a little different that works well.

$arr = array("YD-100 BLACK", "YD-100 GREEN", "YD-100 RED", "YJ-100 BLACK");
//split model number from color
$model = explode(" ",$arr[0])
//find all values that match the model number
$match_values = array_filter($arr, function($val,$key) use (&$model) { return stristr($val, $model[0]);}, ARRAY_FILTER_USE_BOTH);
//returns
//[0] => YD-100 BLACK
//[1] => YD-100 GREEN
//[2] => YD-100 RED

This will only work with PHP 5.6.0 and above.

JJJ
  • 3,314
  • 4
  • 29
  • 43
  • This is a departure from the OP's question / sample data / requirements. – mickmackusa May 11 '21 at 10:10
  • @mickmackusa this appeared first on Google when looking for a solution and since none of the aforementioned solutions helped me, I had to come up with my own solution. I posted it so others looking for a solution could benefit from it. – JJJ May 22 '21 at 22:11
  • When you have a new question which is not solved by a pre-existing page, ask a new question then self-answer it. This way question deviation is avoided. Answers posted on a given page are expected to solve the OP's question, but your answer ignores the OP's question. – mickmackusa May 22 '21 at 23:47
  • Furthermore, `ARRAY_FILTER_USE_BOTH` is useless here and the php manual advises against the use of `strstr()` as a means to check if a substring exists. `strstr($arr[0], ' ', true)` should grab the leading substring. There is no reason to make the leading substring modifiable by reference because you never modify it. – mickmackusa May 22 '21 at 23:50