正则表达式匹配给定字符串的所有组合
Regex to match all combinations of a given string
我正在尝试制作一个正则表达式来匹配给定字符串的所有组合。例如字符串是“1234”,答案将包括:
- “1”
- “123”
- "4321"
- "4312"
非示例包括:
- “11”
- “11234”
- "44132"
如果重要的话,我使用的编程语言是javascript。
感谢您的帮助。
您可以在正则表达式中使用这种基于前瞻性的断言:
^(?!(?:[^1]*1){2})(?!(?:[^2]*2){2})(?!(?:[^3]*3){2})(?!(?:[^4]*4){2})[1234]+$
这里我们有 4 个先行断言:
(?!(?:[^1]*1){2})
:断言我们没有超过一个 1
的实例
(?!(?:[^2]*2){2})
:断言我们没有超过一个 2
的实例
(?!(?:[^3]*3){2})
:断言我们没有超过一个 3
的实例
(?!(?:[^4]*4){2})
:断言我们没有超过一个 4
的实例
我们使用[1234]+
来匹配具有这4个字符的任何字符串。
您不需要为此使用正则表达式。下面的代码片段执行以下操作:
- 遍历可能的组合(
a => s
)(1
、123
、4321
等)
- 复制当前组合以免覆盖它(
s2 = s
)
- 循环测试字符串的字符 (
x => ch
) (1234
=> 1
, 2
, 3
, 4
)
- 替换与测试字符串共享的组合字符串中的常用字符(
s2.replace
)
- 例如在组合
1
中,当循环到达 1234
中的字符 1
时,1
将被替换,导致空字符串
- 如果组合字符串的长度达到
0
(s2.length == 0
) 将结果写入控制台并跳出循环(继续尝试替换空字符串没有意义)
const x = "1234"
const a = ["1","123","4321","4312","11","11234","44132"]
a.forEach(function(s) {
var s2 = s
for(var ch of x) {
s2 = s2.replace(ch, '')
if(s2.length == 0) {
console.log(s);
break;
}
}
})
结果:
1
123
4321
4312
使用字符 classes 的组捕获和使用反向引用的否定前瞻断言的组合可以达到目的。
让我们首先使用字符 class、[1-4]
简单地匹配 1、2、3 和 4 的任意组合,并允许 1 到 4 个字符的任意长度。 {1,4}
。
const regex = /^[1-4]{1,4}$/;
// Create set of inputs from 0 to 4322
const inputs = Array.from(new Array(4323), (v, i) => i.toString());
// Output only values that match criteria
console.log(inputs.filter((input) => regex.test(input)));
当该代码为运行时,很容易看出,虽然只匹配由 1、2、3、4 的某种组合组成的数字,但它也匹配具有重复组合的数字(例如 11 、22、33、112 等)。显然,这不是我们想要的。
要防止重复字符,需要引用先前匹配的字符,然后从任何后续匹配的字符中取反。否定前瞻,(?!...)
使用反向引用,-9
,可以实现这一点。
在前面的例子的基础上,输入的一个子集(目前限制为两个字符的最大长度)现在将围绕第一个字符 ([1-4])
进行组匹配,后跟一个负数使用对第一个捕获 (?!)
的反向引用进行前瞻,最后是第二个可选字符 class.
const regex = /^([1-4])(?!)[1-4]?$/;
// Create set of inputs from 0 to 44
const inputs = Array.from(new Array(45), (v, i) => i.toString());
// Output only values that match criteria
console.log(inputs.filter((input) => regex.test(input)));
这将匹配所需的字符,没有重复!
扩展此模式以包括每个先前匹配的字符的反向引用,最大长度为 4 会产生以下表达式。
const regex = /^([1-4])((?!)[1-4])?((?!|)[1-4])?((?!||)[1-4])?$/;
// Create set of inputs from 0 to 4322
const inputs = Array.from(new Array(4323), (v, i) => i.toString());
// Output only values that match criteria
console.log(inputs.filter((input) => regex.test(input)));
希望对您有所帮助!
我正在尝试制作一个正则表达式来匹配给定字符串的所有组合。例如字符串是“1234”,答案将包括:
- “1”
- “123”
- "4321"
- "4312"
非示例包括:
- “11”
- “11234”
- "44132"
如果重要的话,我使用的编程语言是javascript。
感谢您的帮助。
您可以在正则表达式中使用这种基于前瞻性的断言:
^(?!(?:[^1]*1){2})(?!(?:[^2]*2){2})(?!(?:[^3]*3){2})(?!(?:[^4]*4){2})[1234]+$
这里我们有 4 个先行断言:
(?!(?:[^1]*1){2})
:断言我们没有超过一个1
的实例
(?!(?:[^2]*2){2})
:断言我们没有超过一个2
的实例
(?!(?:[^3]*3){2})
:断言我们没有超过一个3
的实例
(?!(?:[^4]*4){2})
:断言我们没有超过一个4
的实例
我们使用[1234]+
来匹配具有这4个字符的任何字符串。
您不需要为此使用正则表达式。下面的代码片段执行以下操作:
- 遍历可能的组合(
a => s
)(1
、123
、4321
等) - 复制当前组合以免覆盖它(
s2 = s
) - 循环测试字符串的字符 (
x => ch
) (1234
=>1
,2
,3
,4
) - 替换与测试字符串共享的组合字符串中的常用字符(
s2.replace
)- 例如在组合
1
中,当循环到达1234
中的字符1
时,1
将被替换,导致空字符串
- 例如在组合
- 如果组合字符串的长度达到
0
(s2.length == 0
) 将结果写入控制台并跳出循环(继续尝试替换空字符串没有意义)
const x = "1234"
const a = ["1","123","4321","4312","11","11234","44132"]
a.forEach(function(s) {
var s2 = s
for(var ch of x) {
s2 = s2.replace(ch, '')
if(s2.length == 0) {
console.log(s);
break;
}
}
})
结果:
1
123
4321
4312
使用字符 classes 的组捕获和使用反向引用的否定前瞻断言的组合可以达到目的。
让我们首先使用字符 class、[1-4]
简单地匹配 1、2、3 和 4 的任意组合,并允许 1 到 4 个字符的任意长度。 {1,4}
。
const regex = /^[1-4]{1,4}$/;
// Create set of inputs from 0 to 4322
const inputs = Array.from(new Array(4323), (v, i) => i.toString());
// Output only values that match criteria
console.log(inputs.filter((input) => regex.test(input)));
当该代码为运行时,很容易看出,虽然只匹配由 1、2、3、4 的某种组合组成的数字,但它也匹配具有重复组合的数字(例如 11 、22、33、112 等)。显然,这不是我们想要的。
要防止重复字符,需要引用先前匹配的字符,然后从任何后续匹配的字符中取反。否定前瞻,(?!...)
使用反向引用,-9
,可以实现这一点。
在前面的例子的基础上,输入的一个子集(目前限制为两个字符的最大长度)现在将围绕第一个字符 ([1-4])
进行组匹配,后跟一个负数使用对第一个捕获 (?!)
的反向引用进行前瞻,最后是第二个可选字符 class.
const regex = /^([1-4])(?!)[1-4]?$/;
// Create set of inputs from 0 to 44
const inputs = Array.from(new Array(45), (v, i) => i.toString());
// Output only values that match criteria
console.log(inputs.filter((input) => regex.test(input)));
这将匹配所需的字符,没有重复!
扩展此模式以包括每个先前匹配的字符的反向引用,最大长度为 4 会产生以下表达式。
const regex = /^([1-4])((?!)[1-4])?((?!|)[1-4])?((?!||)[1-4])?$/;
// Create set of inputs from 0 to 4322
const inputs = Array.from(new Array(4323), (v, i) => i.toString());
// Output only values that match criteria
console.log(inputs.filter((input) => regex.test(input)));
希望对您有所帮助!