假设我有一个字符集[ABC],我正在寻找一个正则表达式,它能匹配除空集之外的超集的任何排列,即
[ABC]
ABC ACB BAC BCA CAB CBA AB BC AC CB CA BA A B C
正则表达式应该(显然)* 不 * 匹配空字符串。另一种表达相同目标的方法是“匹配任何包含集合中每个字符的非空字符串最多一次”。更新:集合[ABC]只是一个例子,因为真实的的集合也可能更大。对于这个问题,我希望找到一个“一般”的解决方案,而不是[ABC]的特定解决方案。
1wnzp6jl1#
我相信这个问题可以用正则表达式来解决。
/^([ABC])(?!\1)([ABC])?(?!\1|\2)[ABC]?$/
如果您需要在线演示,请告诉我。
tjjdgumg2#
感谢你的答案(特别是anubhava的和codadicent的)我能够找到这个解决方案,我认为这是相当优雅的,因为它允许键入一次集合:
\b(([ABC])(?!.*\2))+\b
需要\b来匹配全字;省略它们也会找到与所需属性相关的子词。要匹配一个完整的字符串,很明显应该这样做:
\b
^(([ABC])(?!.*\2))+$
vu8f3i0k3#
试试看:
([ABC]?)(?!.*\1)([ABC]?)(?!.*\2)[ABC]?
它只是[ABC]?重复3次,并添加了对不允许重复字符的否定lookaheadAssert的检查。请注意,仅当输入集都是唯一的时,这才有效。See it work
[ABC]?
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
ukqbszuj5#
这不是正则表达式所擅长的。您可能只想创建一个排列列表,然后生成所有唯一的子字符串。类似于:
def matches(s, characters): if len(s) != len(set(s)): return False # not unique sequence of characters return set(s).issubsetof(set(characters))
a11xaf1n6#
试试这个:(已更新)
A[BC](?![ABC])|B[AC](?![ABC])|C[AB](?![ABC])|[ABC](?![ABC])|(ABC|ACB|BAC|BCA|CAB|CBA)(?![ABC])
示范:
http://regexr.com?30pa6
xkrw2x1b7#
以下是我的版本:
\b(?=[ABC]{1,3})([ABC]{1})(?:(?!\1)([ABC]{1})(?:(?!\1)(?!\2)[ABC]{1})?)?\b
逻辑:
(?=[ABC]{1,3})
([ABC]{1})
(?!\1)([ABC]{1})
(?!\1)(?!\2)[ABC]{1}
我用这个输入测试了它,所以它看起来相当可靠:英国广播公司英国广播公司英国广播公司
编辑:
正如你提到的字符集可以更大,我会遵循PS的建议,在你的问题,并这样做的方式如下:
chars
inputStrings
string
string.length <= inputStrings.length
matches
ylamdve68#
好的,我必须说,我已经考虑了你的问题很多,因为你似乎想要一些真正通用和可定制的东西(以支持尽可能多的元素,等等),这是我认为会使最佳的解决方案。从数学的Angular 来看,您需要的是确定一组元素的所有排列,而不需要重复。
找到集合的所有排列,重复(并将它们存储在数组中)
[ABC]([ABC]{1,2})?
***旁注:*假设您有一个包含n元素的集合,您所要做的就是:
n
[elements]([elements]{1,n-1})?
过滤所有具有重复元素的排列
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
8条答案
按热度按时间1wnzp6jl1#
我相信这个问题可以用正则表达式来解决。
如果您需要在线演示,请告诉我。
tjjdgumg2#
感谢你的答案(特别是anubhava的和codadicent的)我能够找到这个解决方案,我认为这是相当优雅的,因为它允许键入一次集合:
需要
\b
来匹配全字;省略它们也会找到与所需属性相关的子词。要匹配一个完整的字符串,很明显应该这样做:vu8f3i0k3#
试试看:
它只是
[ABC]?
重复3次,并添加了对不允许重复字符的否定lookaheadAssert的检查。请注意,仅当输入集都是唯一的时,这才有效。
See it work
flseospp4#
它是A| B| C,每个值后面都可以跟一对可选值
而不是ACAC、AA或ACC。以B或C作为第一个字符的情况是等效的。
对于更长的字符串,这很快就会变得很难看。一个更好的方法是(伪代码):
ukqbszuj5#
这不是正则表达式所擅长的。您可能只想创建一个排列列表,然后生成所有唯一的子字符串。
类似于:
a11xaf1n6#
试试这个:(已更新)
示范:
http://regexr.com?30pa6
xkrw2x1b7#
以下是我的版本:
逻辑:
\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
是否matches
列表中找到的匹配数matches
列表是否包含任何条目,然后检查所有条目是否== 1或0 }ylamdve68#
好的,我必须说,我已经考虑了你的问题很多,因为你似乎想要一些真正通用和可定制的东西(以支持尽可能多的元素,等等),这是我认为会使最佳的解决方案。
从数学的Angular 来看,您需要的是确定一组元素的所有排列,而不需要重复。
步骤1:
找到集合的所有排列,重复(并将它们存储在数组中)
***旁注:*假设您有一个包含
n
元素的集合,您所要做的就是:[elements]([elements]{1,n-1})?
步骤2:
过滤所有具有重复元素的排列
PHP中的示例代码:
输出: