使用数组中的键搜索字符串并返回第一个符合条件的键的值

问题描述 投票:0回答:4

我有一个像这样的数组:

$array = ['cat' => 0, 'dog' => 1];

我有一个这样的字符串:

$string = 'I like cats.';

我想看看字符串中是否找到了数组中的任何键;如果是这样,我想返回与第一个匹配的键关联的值。

我尝试了以下方法,但显然不起作用。

array_key_exists("I like cats", $array)

假设我可以在给定时间获得任意随机字符串,我该如何做这样的事情?

伪代码:

array_key_exists("I like cats", *.$array.*)
//The value for cat is "0"

请注意,我想检查是否存在任何形式的“cat”。它可以是

cats
cathy
,甚至是像
vbncatnm
这样的随机字母。我从 mysql 数据库获取数组,我需要知道“cat”或“dog”的 ID 是哪个。

php arrays string string-matching array-key-exists
4个回答
7
投票

您可以在键上使用正则表达式。因此,如果字符串中的任何单词等于键,则

$found
就是
true
。如果需要,您可以将
$key
保存在变量中。 preg_match函数允许测试正则表达式。

$found = false;
foreach ($array as $key => $value) {
    //If the key is found in your string, set $found to true
    if (preg_match("/".preg_quote($key)."/", "I like cats")) {
        $found = true;
    }
}

编辑:

正如评论中所说,strpos可能会更好!因此,使用相同的代码,您只需替换 preg_match 即可:

$keys = array_keys($array);
$found = false;
foreach ($keys as $key) {
    //If the key is found in your string, set $found to true
    if (false !== strpos("I like cats", $key)) {
        $found = true;
    }
}

3
投票

这应该可以帮助您实现您想要做的事情:

$array = array('cat' => 10, 'dog' => 1);

$findThis = 'I like cats';

$filteredArray = array_filter($array, function($key) use ($findThis) {
    return strpos($findThis, $key) !== false;
}, ARRAY_FILTER_USE_KEY);

我发现将

array_filter()
函数与闭包/匿名函数一起使用是比
foreach
循环更优雅的解决方案,因为它保持一级缩进。


1
投票

您可以使用 preg_match ,其值不在数组中,而是在搜索条件中

 if(preg_match('~(cat|dog)~', "I like cats")) {
    echo 'ok';
}

$criteria = '~(cat|dog)~';

 if (preg_match($criteria, "I like cats")) {
    echo 'ok';
}

否则你可以在数组上使用 foreach

 foreach($array as $key => $value ) {
     $pos = strpos("I like cats", $key);
     if ($pos > 0) {
      echo $key .  ' '. $value;
     }

 }

0
投票

对于以下演示,假设以下输入数据:

$haystack = "I like cats.";
$needles = ['cat' => 0, 'dog' => 1];

对于所有实现,请注意,由于问题中描述的任务期望返回合格“键”的“值”,因此脚本需要区分积极结果(可能返回

0
false
、数组、
null
,或实际上任何数据类型)和负面结果。

因此,如果将解决方案内置到函数中,当搜索无法找到匹配项时,可以通过抛出异常来享受清晰性,以便调用脚本可以捕获该异常。当然,您也可以选择不在自定义函数中包含该流程。


  • 就效率而言,使用函数迭代可能不是一个明智的选择。默认情况下,函数迭代器(如

    array_filter()
    )即使在找到所需内容后也会继续迭代。这意味着浪费周期。 演示

    function inefficient(string $haystack, array $needles) {
        $qualifiers = array_filter(
            $needles,
            fn($k) => strpos($haystack, $k) !== false,
            ARRAY_FILTER_USE_KEY
        );
        if (!$qualifiers) {
            throw new Exception('No needles were found in the haystack');
        }
        return current($qualifiers);
    }
    try {
        var_export(inefficient($haystack, $needles));    
    } catch (Exception $e) {
        echo $e->getMessage();
    }
    

  • 使用正则表达式需要一些准备工作,并且根据涉及的数据量,可能不是超级高性能,但这并不是一个荒谬的方法。我不赞成进行迭代的正则表达式调用;使用文字字符串匹配来执行此操作实际上与调用

    strpos()
    相同,但对资源的负担更大(这没有意义)。对于 PHP 来说,构建管道分隔模式的工作量会更少,然后只搜索字符串一次。

    请注意,在不指定模式分隔符作为第二个参数的情况下调用

    preg_quote
    是安全的,因为所使用的模式由
    #
    分隔——该字符默认由
    preg_quote()
    转义。 演示

    function regex(string $haystack, array $needles) {
        $regex = implode('|', array_map('preg_quote', array_keys($needles)));
        if (!preg_match("#$regex#", $haystack, $m)) {
            throw new Exception('No needles were found in the haystack');
        }
        return $needles[$m[0]];
    }
    try {
        var_export(regex($haystack, $needles));    
    } catch (Exception $e) {
        echo $e->getMessage();
    }
    

  • 使用经典的

    foreach()
    与条件/早期
    return
    break
    对于某些开发人员来说可能不会被认为是最 sexy 的方法,但它可能会拥有最好的性能。 演示

    function earlyReturn(string $haystack, array $needles) {
        foreach ($needles as $needle => $value) {
            if (strpos($haystack, $needle) !== false) {
                return $value;
            }
        }
        throw new Exception('No needles were found in the haystack');
    }
    try {
        var_export(earlyReturn($haystack, $needles));    
    } catch (Exception $e) {
        echo $e->getMessage();
    }
    
© www.soinside.com 2019 - 2024. All rights reserved.