regex 正则表达式检查一组字符是否重复

cngwdvgl  于 2022-12-14  发布在  其他
关注(0)|答案(8)|浏览(130)

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

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

正则表达式应该(显然)* 不 * 匹配空字符串。
另一种表达相同目标的方法是“匹配任何包含集合中每个字符的非空字符串最多一次”。
更新:集合[ABC]只是一个例子,因为真实的的集合也可能更大。对于这个问题,我希望找到一个“一般”的解决方案,而不是[ABC]的特定解决方案。

1wnzp6jl

1wnzp6jl1#

我相信这个问题可以用正则表达式来解决。

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

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

tjjdgumg

tjjdgumg2#

感谢你的答案(特别是anubhava的和codadicent的)我能够找到这个解决方案,我认为这是相当优雅的,因为它允许键入一次集合:

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

需要\b来匹配全字;省略它们也会找到与所需属性相关的子词。要匹配一个完整的字符串,很明显应该这样做:

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

vu8f3i0k3#

试试看:

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

它只是[ABC]?重复3次,并添加了对不允许重复字符的否定lookaheadAssert的检查。
请注意,仅当输入集都是唯一的时,这才有效。
See it work

flseospp

flseospp4#

"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
ukqbszuj

ukqbszuj5#

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

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

a11xaf1n6#

试试这个:(已更新)

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

示范:

http://regexr.com?30pa6

xkrw2x1b

xkrw2x1b7#

以下是我的版本:

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

逻辑:

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

我用这个输入测试了它,所以它看起来相当可靠:
英国广播公司英国广播公司英国广播公司

编辑:

正如你提到的字符集可以更大,我会遵循PS的建议,在你的问题,并这样做的方式如下:

  • 引入chars数组,该数组将保存允许集合中的每个字符(将字符串拆分为字符)
  • 获取一个inputStrings的数组(按空格或其他任何要求拆分输入字符串)
  • 对于inputStrings中的每个string {
  • 检查string.length <= inputStrings.length是否
  • try将列表中的每个字符与当前输入进行匹配,并保存在matches列表中找到的匹配数
  • 检查matches列表是否包含任何条目,然后检查所有条目是否== 1或0 }
ylamdve6

ylamdve68#

好的,我必须说,我已经考虑了你的问题很多,因为你似乎想要一些真正通用和可定制的东西(以支持尽可能多的元素,等等),这是我认为会使最佳的解决方案。
从数学的Angular 来看,您需要的是确定一组元素的所有排列,而不需要重复

步骤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

相关问题