【发布时间】:2017-05-06 10:50:37
【问题描述】:
我需要检查一个查询字符串是否仅由少于 4 个字符的单词组成,如果是,则删除所有空格。
类似:this has four character words or higher
... 将返回 FALSE
类似:hd 1 kit
... 将返回 TRUE,因为字符串中的单词不超过 3 个字符。
我会尝试对其进行编码,但对于如何为此类内容编写正则表达式一无所知。
【问题讨论】:
我需要检查一个查询字符串是否仅由少于 4 个字符的单词组成,如果是,则删除所有空格。
类似:this has four character words or higher
... 将返回 FALSE
类似:hd 1 kit
... 将返回 TRUE,因为字符串中的单词不超过 3 个字符。
我会尝试对其进行编码,但对于如何为此类内容编写正则表达式一无所知。
【问题讨论】:
您可以使用@SahilGulati 建议的正则表达式来执行此操作,但使用explode() 可能更有效:
$string = "this has four character words or higher";
$array = explode(" ", $string);
$success = true;
foreach ($array as $word) {
if(strlen($word) < 4) {
$success = false;
break;
}
}
if($success) {
echo "ok";
} else {
echo "nok";
}
这是live example。
here 是使用正则表达式和非正则表达式的实时比较(不使用正则表达式时大约快 35%):
<?php
function noRegex() {
$string = "this has four character words or higher";
$array = explode(" ", $string);
$success = true;
foreach ($array as $word) {
if(strlen($word) < 4) {
$success = false;
break;
}
}
return $success;
}
function regex() {
$string = "this has four character words or higher";
$success = false;
if(!preg_match_all("/\b[a-zA-Z0-9]{4}\b/", $string)) {
$success = true;
}
return $success;
}
$before = microtime(true);
for($i=0; $i<2000000; $i++) {
noRegex();
}
echo "no regex: ";
echo $noRegexTime = microtime(true) - $before;
echo $noRegexTime;
echo "\n";
$before = microtime(true);
for($i=0; $i<2000000; $i++) {
regex();
}
echo "regex: ";
echo $regexTime = microtime(true) - $before;
echo $regexTime;
echo "\n";
echo "Not using regex is " . round((($regexTime / $noRegexTime) - 1) * 100, 2) . "% faster than using regex.";
?>
【讨论】:
$query = (!preg_match_all("/\b[a-zA-Z0-9]{4,}\b/", $query) ? str_replace(" ","",$query) : $query );
preg_match_all? return (bool)!preg_match("/\b[a-zA-Z0-9]{4}/", $string); 它的性能优于 noregex。
希望这个简单的解决方案能帮到你。
正则表达式: /\b[a-zA-Z0-9]{4,}\b/
1.
\b[a-zA-Z0-9]{4,}\b将匹配四个字符,\b用于边界条件。
<?php
$string1="this has four character words or higher";
$string2="hd 1 kit";
if(!preg_match_all("/\b[a-zA-Z0-9]{4,}\b/", $string1))
{
echo "Should be allowed";
}
【讨论】:
I am Sahil。这没有4 字符的单词,但它应该被禁止..
if (!preg_match("/\b[a-zA-Z0-9]{4}/", $string1))
如果字符串中没有标点符号,那么最有效的方法是使用strpos:
function checkWordsLenght($string, $limit)
{
$offset = 0;
$string .= ' ';
while(($position = strpos($string, ' ', $offset)) !== false) {
if (($position - $offset) > $limit) {
return false;
}
$offset = $position + 1;
}
return true;
}
这里是working demo。
【讨论】:
重要的是,在提供基于正则表达式的解决方案时,被视为“最佳”的答案是最精炼的。这意味着提供最准确的结果,当结果准确度并列时,性能应该是下一个标准,其次是模式简洁性。
出于这个原因,我不得不发布一个优于当前接受的答案的答案。我将使用 V_RocKs 在 ssc-hrep3 的答案下的评论中使用的变量名。
使用第一个示例字符串的代码:
$query="this has four character words or higher";
$query=preg_match("/[^ ]{4,}/",$query)?str_replace(" ","",$query):$query;
echo "$query";
输出:
thishasfourcharacterwordsorhigher
使用第二个示例字符串的代码:
$query="hd 1 kit";
$query=preg_match("/[^ ]{4,}/",$query)?str_replace(" ","",$query):$query;
echo "$query";
输出:
hd 1 kit
我的正则表达式模式不仅同样准确,而且更短、更高效(需要更少的步骤)。对于这个问题,边界字符的使用是不必要的,它会对性能产生近 50% 的负面影响。
从模式中删除单词边界后,有几种方法可以定位所需的子字符串。以下模式具有完全相同的含义和steps 计数:
/[a-zA-Z0-9]{4,}//[a-z0-9]{4,}/i/[a-z\d]{4,}/i/[^ ]{4,}/我的观点是:读者来 SO 并不是为了寻找“嗯,这已经足够好”的答案了,他们来这里是为了从才华横溢、多元化的 SO 社区的庞大知识库中汲取灵感/教育方法。让我们努力在每个答案上实现最佳方法,以便未来的读者可以从我们的见解中学习,并接受所有编码语言所提供的教育。
当次优模式在 SO 上获得支持/绿色标记时,就错失了正确教育读者完成编码任务的最佳方法的机会。
【讨论】: