我有一些字符串的组,我需要通过正则表达式查找所有组,其中组的顺序是不相关的
请,我需要在用户的答案中找到所有必要的成分。用户可以将原料放在任何顺序,他可以由任何字符或字符串(空格,逗号)或分隔符是不必要的。
$string = "banana, strawberry, cherry and chocolate";
$regex = "/(banana)*(strawberry)*(cherry)*(chocolate)/";
if (preg_match($regex, $string)) {
// do something
}
我的代码中的问题是,如果用户的答案是“草莓,香蕉,樱桃”,preg_match会验证这是真的,这很糟糕,因为巧克力也是答案中的必需品。或者如果我输入"strwberry“而不是strawberry,这也是真的吗?用户的答案必须包括所有4种成分在任何顺序,他不能有打字错误的名称的成分。非常感谢您的任何提示。
发布于 2019-06-27 06:48:18
关于您的请求的:
用户可以按任何顺序放置配料,并且可以用任何字符或字符串(空格、逗号)分隔,分隔符不是必需的。
配料的顺序不是问题,我们稍后会看到。但是没有分隔符是一个非常糟糕的想法!考虑下面的例子(水果沙拉):
$ingredients = ['melon', 'orange', 'grape', 'apple'];
$userAnswer = 'watermelonorangegrapeapple';
问题很明显,没有办法用这种类型的约束来区分“甜瓜”和“西瓜”,这会导致误报。
不要忘记,用户要对他写的东西负责,当他没有得到想要的结果时,他会从自己的错误中吸取教训。另一种方法是强制用户使用输入字段逐个输入配料。
用户的答案必须包括所有4种成分在任何顺序,他不能有打字错误的名称中的成分。
为什么不呢,但在我看来,这一次你太狭隘了:如果用户写的是"strawberry“而不是”strawberry“怎么办?这不是真正的打字错误,我认为这是可以接受的。
Possibilities:
让我们假设在所有可能的世界中,一切都是最好的:单词是有分隔符的,没有打字错误。
按照previously linked question中的建议,您可以执行以下操作:
if ( preg_match('~(?=.*\bword1\b)(?=.*\bword2\b)(?=.*\bword3\b)(?=.*\bword4\b)~Ai', $userAnswer) ) {
//...
}
但这并不是紧凑的、切中你梦想的方式:
,delimiters.
其他方法:您可以使用分隔符拆分用户字符串,并使用array_diff
查看是否存在每种成分。
基本信息:
$delimiter = '~ \b \s* (?: , \s* | \s and \s+ ) ~uxi';
$parts = preg_split($delimiter, $userAnswer, -1, PREG_SPLIT_NO_EMPTY);
if ( empty(array_diff($ingredients, $parts)) ) {
// all ingredients are here
}
使用清理:
$delimiter = '~ \b (?: [ ]? , [ ]? | [ ] and [ ] ) ~ux';
$userAnswer = trim(preg_replace('~[\s\pP]+~u', ' ', mb_strtolower($userAnswer)));
$parts = preg_split($delimiter, $userAnswer);
if ( empty(array_diff($ingredients, $parts)) ) {
// all ingredients are here
}
在字符串之间进行宽松的比较:
$delimiter = '~ \b (?: [ ]? , [ ]? | [ ] and [ ] ) ~ux';
$userAnswer = trim(preg_replace('~[\s\pP]+~', ' ', mb_strtolower($userAnswer)));
$parts = preg_split($delimiter, $userAnswer);
if ( empty(array_udiff($ingredients, $parts, $callback)) ) {
// all ingredients are here
}
回调函数示例:
array_udiff
的回调函数只不过是对数组进行排序的比较函数,换句话说,排序是比较两个数组的必要步骤。这就是为什么两个项目之间的比较应该得到一个正的,负的整数或0来确定顺序。
PHP有两个函数可以在字符串之间执行模糊比较:similar_text()
和levenshtein()
。
一个使用levenshtein距离的例子。小于2表示只能替换、插入或删除一个字符,以使两个字符串相等(有关更多控制,请参阅PHP手册)。
$callback = function ($a, $b) {
return levenshtein($a, $b) < 2 ? 0
: ( $a < $b ? -1 : 1 );
}
请注意,这两个函数对于长字符串可能具有不可忽略的成本,因为similar_text()
是O(max (m,n)^3),而levenshtein()
是O(m*n) (m和n是字符串的长度)。如果出现问题,您还可以在比较字符串之前使用metaphone()
或soundex()
等函数转换字符串,或者编写自己的转换。这涉及到必须提前修改包含成分的数据结构,以便更容易地进行比较。
https://stackoverflow.com/questions/56733096
复制相似问题