首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >搜索组顺序不相关的字符串的组

搜索组顺序不相关的字符串的组
EN

Stack Overflow用户
提问于 2019-06-24 16:57:59
回答 1查看 44关注 0票数 1

我有一些字符串的组,我需要通过正则表达式查找所有组,其中组的顺序是不相关的

请,我需要在用户的答案中找到所有必要的成分。用户可以将原料放在任何顺序,他可以由任何字符或字符串(空格,逗号)或分隔符是不必要的。

代码语言:javascript
复制
$string = "banana, strawberry, cherry and chocolate";
$regex = "/(banana)*(strawberry)*(cherry)*(chocolate)/";
if (preg_match($regex, $string)) {
 // do something
}

我的代码中的问题是,如果用户的答案是“草莓,香蕉,樱桃”,preg_match会验证这是真的,这很糟糕,因为巧克力也是答案中的必需品。或者如果我输入"strwberry“而不是strawberry,这也是真的吗?用户的答案必须包括所有4种成分在任何顺序,他不能有打字错误的名称的成分。非常感谢您的任何提示。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-27 06:48:18

关于您的请求的

用户可以按任何顺序放置配料,并且可以用任何字符或字符串(空格、逗号)分隔,分隔符不是必需的。

配料的顺序不是问题,我们稍后会看到。但是没有分隔符是一个非常糟糕的想法!考虑下面的例子(水果沙拉):

代码语言:javascript
复制
$ingredients = ['melon', 'orange', 'grape', 'apple'];
$userAnswer = 'watermelonorangegrapeapple';

问题很明显,没有办法用这种类型的约束来区分“甜瓜”和“西瓜”,这会导致误报。

不要忘记,用户要对他写的东西负责,当他没有得到想要的结果时,他会从自己的错误中吸取教训。另一种方法是强制用户使用输入字段逐个输入配料。

用户的答案必须包括所有4种成分在任何顺序,他不能有打字错误的名称中的成分。

为什么不呢,但在我看来,这一次你太狭隘了:如果用户写的是"strawberry“而不是”strawberry“怎么办?这不是真正的打字错误,我认为这是可以接受的。

Possibilities:

让我们假设在所有可能的世界中,一切都是最好的:单词是有分隔符的,没有打字错误。

按照previously linked question中的建议,您可以执行以下操作:

代码语言:javascript
复制
if ( preg_match('~(?=.*\bword1\b)(?=.*\bword2\b)(?=.*\bword3\b)(?=.*\bword4\b)~Ai', $userAnswer) ) {
    //...
}

但这并不是紧凑的、切中你梦想的方式:

,delimiters.

  • You,,
  1. ,没有考虑到,必须为每个配料列表动态构建模式。(然而,它不是difficult)
  2. Each lookahead必须遍历整个字符串。
  3. 它根本不灵活,也不具有伸缩性。
  4. 如果你对第2到5点有疑问,请参阅第1点。

其他方法:您可以使用分隔符拆分用户字符串,并使用array_diff查看是否存在每种成分。

基本信息:

代码语言:javascript
复制
$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
}

使用清理:

代码语言:javascript
复制
$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
}

在字符串之间进行宽松的比较:

代码语言:javascript
复制
$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手册)。

代码语言:javascript
复制
$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()等函数转换字符串,或者编写自己的转换。这涉及到必须提前修改包含成分的数据结构,以便更容易地进行比较。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56733096

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档