I am trying to make a regex to matches all the combinations of a given string. For example of the string is "1234", answers would include:
Nonexamples would include:
If it matters, the programming language I am using is javascript.
Thank you for any help.
You may use this lookahead based assertions in your regex:
^(?!(?:[^1]*1){2})(?!(?:[^2]*2){2})(?!(?:[^3]*3){2})(?!(?:[^4]*4){2})[1234]+$
Here we have 4 lookahead assertions:
(?!(?:[^1]*1){2})
: Assert that we don't have more than one instance of 1
(?!(?:[^2]*2){2})
: Assert that we don't have more than one instance of 2
(?!(?:[^3]*3){2})
: Assert that we don't have more than one instance of 3
(?!(?:[^4]*4){2})
: Assert that we don't have more than one instance of 4
We use [1234]+
to match any string with these 4 characters.
A combination of group captures using character classes and negative look-ahead assertions using back-references would do the trick.
Let's begin with simply matching any combination of 1, 2, 3, and 4 using a character class, [1-4]
, and allowing any length from 1 to 4 characters. {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)));
When that code is run, it's easy to see that although only numbers consisting of some combination of 1, 2, 3, and 4 are matched, it also is matching numbers with repeating combinations (eg 11, 22, 33, 112, etc). Obviously, this was not what was desired.
To prevent repeating characters requires a reference to previously matched characters and then a negation of them from any following matched characters. Negative look-aheads, (?!...)
using a back-reference, \\1-9
, can accomplish this.
Building on the previous example with a subset of the inputs (limiting to a max length of two characters for the moment) would now incorporate a group match surrounding the first character, ([1-4])
, followed by a negative look-ahead with a back-reference to the first capture, (?!\\1)
, and finally a second optional character class.
const regex = /^([1-4])(?!\\1)[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)));
This matches the desired characters with no repetition!
Expanding this pattern to include back-references for each of the previously matched characters up to the desired max length of 4 yields the following expression.
const regex = /^([1-4])((?!\\1)[1-4])?((?!\\1|\\2)[1-4])?((?!\\1|\\2|\\3)[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)));
Hope this helps!
You don't need to use regex for this. The snippet below does the following:
a => s
) ( 1
, 123
, 4321
, etc.) s2 = s
) x => ch
) ( 1234
=> 1
, 2
, 3
, 4
) s2.replace
)
1
, the 1
will be replaced when the loop gets to the character 1
in 1234
resulting in an empty string 0
( s2.length == 0
) write the result to the console and break out of the loop (no point in continuing to attempt to replace on an empty string) 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; } } })
Results:
1
123
4321
4312
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.