正则表达式检查不重复的一组字符

时间:2012-04-26 11:56:44

标签: regex permutation superset

假设我有一组字符[ABC]。我正在寻找一个与超集的任何排列匹配的正则表达式,除了空集,即。

ABC ACB BAC BCA CAB CBA
AB BC AC CB CA BA
A B C

正则表达式(显然)匹配空字符串。

P.S。表达相同目标的另一种方法是“匹配至少包含一次集合中每个字符的任何非空字符串”。

更新:集合[ABC]只是一个例子,因为真实集合也可能更大。有了这个问题,我希望找到一个“通用”解决方案而不是[ABC]的特定解决方案。

8 个答案:

答案 0 :(得分:6)

我相信这可以通过正则表达式来解决。使用此正则表达式:

/^([ABC])(?!\1)([ABC])?(?!\1|\2)[ABC]?$/

如果您需要在线演示,请告诉我。

答案 1 :(得分:3)

感谢你的回答(尤其是anubhava和codaddict),我能够找到这个解决方案,我觉得它非常优雅,因为它只允许输入一次:

\b(([ABC])(?!.*\2))+\b

需要\b来匹配完整的字词;省略它们也会找到关于所需属性的子词。要匹配一个完整的字符串,你显然会这样做:

^(([ABC])(?!.*\2))+$

答案 2 :(得分:1)

这不是正则表达式擅长的东西。您可能只想创建一个排列列表,然后生成所有唯一的子串。

类似的东西:

def matches(s, characters):
    if len(s) != len(set(s)):
        return False # not unique sequence of characters
    return set(s).issubsetof(set(characters))

答案 3 :(得分:1)

尝试:

([ABC]?)(?!.*\1)([ABC]?)(?!.*\2)[ABC]?

只有[ABC]?重复3次,并添加了对不允许重复字符的否定先行断言的检查。

请注意,仅当输入集全部唯一时才会起作用。

See it work

答案 4 :(得分:1)

"A((B?C?)|(C?B?))|B((A?C?)|(C?A?))|C((A?B?)|(B?A?))"

它是A | B | C,每个都可以跟随一对可选值

 A(B?C?) matches A, AB,AC and ABC
 A(C?B?) matches A, AC,AB and ACB 

但不是ACAC,AA或ACC。 B或C作为第一个字符的情况是等价的。

对于更长的字符串,这很快就会变得难看。更好的方法是(伪代码):

 string.sort().matches ("^A?B?C?$") && string.length > 0

答案 5 :(得分:0)

试试这个:(更新)

A[BC](?![ABC])|B[AC](?![ABC])|C[AB](?![ABC])|[ABC](?![ABC])|(ABC|ACB|BAC|BCA|CAB|CBA)(?![ABC])

演示:

http://regexr.com?30pa6

答案 6 :(得分:0)

这是我的版本:

\b(?=[ABC]{1,3})([ABC]{1})(?:(?!\1)([ABC]{1})(?:(?!\1)(?!\2)[ABC]{1})?)?\b

逻辑:

  • \b:寻找单词边界
  • (?=[ABC]{1,3}):预见是否存在长度= 3的字符串,其值仅为A,B,C
  • ([ABC]{1}):匹配第一个字符 然后可选择
  • (?!\1)([ABC]{1}):检查下一个字符是否与先前匹配的字符不同 - 如果不匹配,则匹配 并可选择
  • (?!\1)(?!\2)[ABC]{1}:检查下一个字符是否与之前匹配的字符1或2不同 - 如果不匹配,则匹配字符

我针对此输入进行了测试,因此看起来非常可靠:

AABCC BBCC AB BC AC CB CA BA A B C. ABC ACB BAC BCA CAB CBA AAA ABB AAA BBC AA


编辑:

正如你所提到的,字符集可能更大我会在你的问题中遵循PS建议并按以下方式执行:

  • 引入chars数组,该数组将每个字符保存在允许的集合中(将字符串拆分为字符)

  • 获取一个inputStrings数组(在空白处或其他任何需要的地方拆分输入字符串)

  • {li>

    string中的每个inputStrings {

  • 检查string.length <= inputStrings.length
  • 针对当前输入尝试匹配列表中的每个字符,并保存matches列表中找到的匹配项数
  • 检查matches列表是否包含任何条目,然后检查所有条目是否== 1或0 }

答案 7 :(得分:0)

好吧,我必须说我已经考虑了很多问题 - 因为你似乎想要一些真正普遍和可定制的东西(以尽可能多地支持元素等) - 这就是我认为会做的最佳解决方案。

从数学的角度来看,你想要的是识别一组元素的所有排列而不重复


第1步:

查找集合的所有排列,重复(并将它们存储在数组中)

[ABC]([ABC]{1,2})?

旁注:假设您有一个包含n元素的集合,您所要做的就是:

[elements]([elements]{1,n-1})?


第2步:

使用重复元素过滤所有排列

PHP中的示例代码:

<?php

    function strToArray($str)
    {
        $i = 0;

        while (isset($str[$i]))
        {
            $result[$i] = $str[$i];
            $i++;
        }

        return $result;
    }

    function noDuplicates($str)
    {
        if (array_unique(strToArray($str))==strToArray($str)) return true;
        else return false;
    }

    $AAA = "AAA";
    $ABC = "ABC";

    if (noDuplicates($AAA)) echo "$AAA : ok"; else echo "$AAA : not ok\n";
    if (noDuplicates($ABC)) echo "$ABC : ok"; else echo "$ABC : not ok\n";

?>

输出

AAA : not ok
ABC : ok