考虑:
$a = 'How are you?';
if ($a contains 'are')
echo 'true';
假设我有上述代码,正确的写法是什么样的语句if ($a contains 'are')
?
考虑:
$a = 'How are you?';
if ($a contains 'are')
echo 'true';
假设我有上述代码,正确的写法是什么样的语句if ($a contains 'are')
?
if (str_contains('How are you', 'are')) {
echo 'true';
}
str_contains
函数将始终返回true。$haystack = 'Hello';
$needle = '';
if (str_contains($haystack, $needle)) {
echo "This returned true!";
}
$haystack = 'How are you?';
$needle = '';
if ($needle !== '' && str_contains($haystack, $needle)) {
echo "This returned true!";
} else {
echo "This returned false!";
}
输出: 这返回了false!
值得注意的是,新的str_contains
函数是区分大小写的。
$haystack = 'How are you?';
$needle = 'how';
if ($needle !== '' && str_contains($haystack, $needle)) {
echo "This returned true!";
} else {
echo "This returned false!";
}
输出: 这个返回了false!
PHP 8之前
你可以使用strpos()
函数来查找一个字符串在另一个字符串中的出现位置:
$haystack = 'How are you?';
$needle = 'are';
if (strpos($haystack, $needle) !== false) {
echo 'true';
}
!== false
是有意的(既不是!= false
也不是=== true
会返回所需的结果);strpos()
要么返回针在堆栈中开始的偏移量,要么返回布尔值false
如果未找到针。由于0是有效的偏移量且0是“假值”,我们不能使用更简单的结构,如!strpos($a, 'are')
。strpos
更好。对于are
的strpos
检查也会返回类似fare、care、stare等字符串的true结果。使用单词边界即可在正则表达式中避免这些意外匹配。are
的正则表达式如下:$a = 'How are you?';
if (preg_match('/\bare\b/', $a)) {
echo 'true';
}
就性能而言,strpos
大约快三倍。我一次进行了一百万次比较,preg_match
花费了 1.5 秒才完成,而 strpos
则只用了 0.5 秒。
编辑: 为了搜索字符串中的任意部分而不是逐个单词搜索,我建议使用正则表达式,例如
$a = 'How are you?';
$search = 'are y';
if(preg_match("/{$search}/i", $a)) {
echo 'true';
}
正则表达式末尾的 i
可以将正则表达式设置为不区分大小写,如果你不想这样做,可以省略它。
然而,在某些情况下,这可能会造成问题,因为 $search 字符串没有经过任何方式的净化处理。也就是说,它在某些情况下可能无法通过检查,例如当 $search
是用户输入时,他们可以添加一些字符串,这些字符串可能会像某个不同的正则表达式一样运行。
此外,这里有一个很棒的工具,可以测试和查看各种正则表达式的解释:Regex101
要将两组功能合并为一个多用途函数(包括可选择的大小写敏感性),你可以使用类似以下代码:
function FindString($needle,$haystack,$i,$word)
{ // $i should be "" or "i" for case insensitive
if (strtoupper($word)=="W")
{ // if $word is "W" then word search instead of string in string search.
if (preg_match("/\b{$needle}\b/{$i}", $haystack))
{
return true;
}
}
else
{
if(preg_match("/{$needle}/{$i}", $haystack))
{
return true;
}
}
return false;
// Put quotes around true and false above to return them as strings instead of as bools/ints.
}
需要注意的一点是,\b
只在英语之外的语言中无法使用。
这里讲解了原因以及解决方案:
\b
表示单词(词边界)的开始或结束。 此正则表达式将匹配“apple pie”中的“apple”,但不会匹配“pineapple”,“applecarts”或“bakeapples”中的“apple”。那么“café”呢? 我们如何在正则表达式中提取单词“café”?
\bcafé\b
实际上不起作用。 为什么? 因为“café”包含非ASCII字符:é。 \b不能简单地与Unicode一起使用,例如समुद्र,감사,месяц和 。当您想提取 Unicode 字符时,应直接定义表示单词边界的字符。
答案是:
(?<=[\s,.:;"']|^)UNICODE_WORD(?=[\s,.:;"']|$)
因此,要在PHP中使用答案,可以使用此函数:
function contains($str, array $arr) {
// Works in Hebrew and any other unicode characters
// Thanks https://medium.com/@shiba1014/regex-word-boundaries-with-unicode-207794f6e7ed
// Thanks https://www.phpliveregex.com/
if (preg_match('/(?<=[\s,.:;"\']|^)' . $word . '(?=[\s,.:;"\']|$)/', $str)) return true;
}
如果您想搜索一个单词数组,您可以使用以下代码:
function arrayContainsWord($str, array $arr)
{
foreach ($arr as $word) {
// Works in Hebrew and any other unicode characters
// Thanks https://medium.com/@shiba1014/regex-word-boundaries-with-unicode-207794f6e7ed
// Thanks https://www.phpliveregex.com/
if (preg_match('/(?<=[\s,.:;"\']|^)' . $word . '(?=[\s,.:;"\']|$)/', $str)) return true;
}
return false;
}
从PHP 8.0.0开始,你现在可以使用str_contains
<?php
if (str_contains('abc', '')) {
echo "Checking the existence of the empty string will always"
return true;
}
这是一个小工具函数,在像这样的情况下非常有用
// returns true if $needle is a substring of $haystack
function contains($needle, $haystack)
{
return strpos($haystack, $needle) !== false;
}
if ($email->contains("@") && $email->endsWith(".com)) { ...
或if (strpos($email, "@") !== false && substr($email, -strlen(".com")) == ".com") { ...
- Brandin您可以使用 PHP 函数 strpos() 来确定一个字符串是否包含另一个字符串。
int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )`
<?php
$haystack = 'how are you';
$needle = 'are';
if (strpos($haystack,$needle) !== false) {
echo "$haystack contains $needle";
}
?>
注意:
如果你要搜索的字符串在目标字符串开头,strpos()
会返回位置0。如果你使用==
比较符号进行比较,这是行不通的,你需要使用===
。
==
是一个比较运算符,用于判断左侧的变量、表达式或常量是否与右侧的变量、表达式或常量具有相同的值。
===
是一个比较运算符,用于判断两个变量、表达式或常量是否相等 且
类型相同 - 也就是说,两者都是字符串或整数类型。
使用这种方法的一个优点是,每个PHP版本都支持此函数,不像str_contains()
一样存在版本兼容性问题。
虽然大多数答案会告诉你如何判断一个字符串中是否包含子串,但如果你要查找特定的 单词 而不是 子串,那通常并不是你想要的。
有什么区别呢?子串可以出现在其他单词中:
缓解这种情况的一种方法是使用正则表达式和单词边界(\b
):
function containsWord($str, $word)
{
return !!preg_match('#\\b' . preg_quote($word, '#') . '\\b#i', $str);
}
这种方法没有上述相同的误报问题,但它有一些自己的边缘情况。单词边界是在非单词字符(\W
)上匹配的,这些字符将是任何不是a-z
,A-Z
,0-9
或_
的字符。这意味着数字和下划线将被视为单词字符,而像这样的情况将失败:
如果您想要比这更准确的内容,那么您就必须开始进行英语语法分析,而这是一个相当棘手的问题(并且无论如何都假设正确使用语法,这并不总是确定的)。
\b
可以匹配两个 \W
无法匹配的东西,这使它非常适合在字符串中查找“单词”:它可以匹配字符串的开头 (^
) 和结尾 ($
)。 - code_monk\\
。https://3v4l.org/ZRpYi - MetalWeirdo查看strpos()
函数:
<?php
$mystring = 'abc';
$findme = 'a';
$pos = strpos($mystring, $findme);
// Note our use of ===. Simply, == would not work as expected
// because the position of 'a' was the 0th (first) character.
if ($pos === false) {
echo "The string '$findme' was not found in the string '$mystring'.";
} else {
echo "The string '$findme' was found in the string '$mystring',";
echo " and exists at position $pos.";
}
strstr($a, 'are')
比丑陋的strpos($a, 'are') !== false
更优雅。PHP真的需要一个str_contains()
函数。 - Paul Spiegel与SamGoody和Lego Stormtroopr的评论同行。
如果您正在寻找一种基于PHP算法来根据多个单词的接近度/相关性对搜索结果进行排名的方法,这里有一个快速简便的PHP生成搜索结果的方法:
其他布尔搜索方法(如strpos()
、preg_match()
、strstr()
或stristr()
)的问题
基于向量空间模型和tf-idf(词频-逆文档频率)的PHP方法:
听起来很难,但实际上非常容易。
如果我们想在字符串中搜索多个单词,核心问题是如何为它们中的每一个分配权重?
如果我们可以根据单词对整个字符串的代表性加权,我们就可以按最符合查询的结果排序。
这是向量空间模型的概念,与SQL全文搜索工作方式相差无几。function get_corpus_index($corpus = array(), $separator=' ') {
$dictionary = array();
$doc_count = array();
foreach($corpus as $doc_id => $doc) {
$terms = explode($separator, $doc);
$doc_count[$doc_id] = count($terms);
// tf–idf, short for term frequency–inverse document frequency,
// according to wikipedia is a numerical statistic that is intended to reflect
// how important a word is to a document in a corpus
foreach($terms as $term) {
if(!isset($dictionary[$term])) {
$dictionary[$term] = array('document_frequency' => 0, 'postings' => array());
}
if(!isset($dictionary[$term]['postings'][$doc_id])) {
$dictionary[$term]['document_frequency']++;
$dictionary[$term]['postings'][$doc_id] = array('term_frequency' => 0);
}
$dictionary[$term]['postings'][$doc_id]['term_frequency']++;
}
//from http://phpir.com/simple-search-the-vector-space-model/
}
return array('doc_count' => $doc_count, 'dictionary' => $dictionary);
}
function get_similar_documents($query='', $corpus=array(), $separator=' '){
$similar_documents=array();
if($query!=''&&!empty($corpus)){
$words=explode($separator,$query);
$corpus=get_corpus_index($corpus, $separator);
$doc_count=count($corpus['doc_count']);
foreach($words as $word) {
if(isset($corpus['dictionary'][$word])){
$entry = $corpus['dictionary'][$word];
foreach($entry['postings'] as $doc_id => $posting) {
//get term frequency–inverse document frequency
$score=$posting['term_frequency'] * log($doc_count + 1 / $entry['document_frequency'] + 1, 2);
if(isset($similar_documents[$doc_id])){
$similar_documents[$doc_id]+=$score;
}
else{
$similar_documents[$doc_id]=$score;
}
}
}
}
// length normalise
foreach($similar_documents as $doc_id => $score) {
$similar_documents[$doc_id] = $score/$corpus['doc_count'][$doc_id];
}
// sort from high to low
arsort($similar_documents);
}
return $similar_documents;
}
案例1
$query = 'are';
$corpus = array(
1 => 'How are you?',
);
$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
print_r($match_results);
echo '</pre>';
结果
Array
(
[1] => 0.52832083357372
)
$query = 'are';
$corpus = array(
1 => 'how are you today?',
2 => 'how do you do',
3 => 'here you are! how are you? Are we done yet?'
);
$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
print_r($match_results);
echo '</pre>';
结果
Array
(
[1] => 0.54248125036058
[3] => 0.21699250014423
)
$query = 'we are done';
$corpus = array(
1 => 'how are you today?',
2 => 'how do you do',
3 => 'here you are! how are you? Are we done yet?'
);
$match_results=get_similar_documents($query,$corpus);
echo '<pre>';
print_r($match_results);
echo '</pre>';
结果
Array
(
[3] => 0.6813781191217
[1] => 0.54248125036058
)
strpos()
、preg_match()
、strstr()
或stristr()
。
注意
可选地,在搜索单词之前消除冗余
用和原词相同或相似的词语进行替换。(例如:将"hungrily"和"hungry"替换为"hunger")
可以执行进一步的算法措施(如snowball)以进一步将单词减少到其基本含义。
使用十六进制等效的颜色名称进行替换。
通过降低精度来减少数字值是归一化文本的其他方法。
资源
以下是您需要翻译的内容:利用strpos()
进行子字符串匹配:
if (strpos($string,$stringToSearch) !== false) {
echo 'true';
}
if (substr_count($a, 'are') > 0) {
echo "at least one 'are' is present!";
}
它比strpos慢一些,但避免了比较问题。
strpos
的位置为 0
,所以它对于“你确定吗?”返回 false
。 - Hafenkranich
strpos($a, 'are') > -1
来测试真值。从调试的角度看,当我不需要计算连续等号的数量时,我觉得我的大脑浪费的时钟周期更少了。 - equazcion