我有一个像这样的数组:
$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 是哪个。
您可以在键上使用正则表达式。因此,如果字符串中的任何单词等于键,则
$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;
}
}
这应该可以帮助您实现您想要做的事情:
$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
循环更优雅的解决方案,因为它保持一级缩进。
您可以使用 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;
}
}
对于以下演示,假设以下输入数据:
$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();
}