最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Regex to match all combinations of a given string - Stack Overflow

programmeradmin6浏览0评论

I am trying to make a regex to matches all the binations of a given string. For example of the string is "1234", answers would include:

  1. "1"
  2. "123"
  3. "4321"
  4. "4312"

Nonexamples would include:

  1. "11"
  2. "11234"
  3. "44132"

If it matters, the programming language I am using is javascript.

Thank you for any help.

I am trying to make a regex to matches all the binations of a given string. For example of the string is "1234", answers would include:

  1. "1"
  2. "123"
  3. "4321"
  4. "4312"

Nonexamples would include:

  1. "11"
  2. "11234"
  3. "44132"

If it matters, the programming language I am using is javascript.

Thank you for any help.

Share asked Apr 17, 2018 at 15:50 Vishnu MurthyVishnu Murthy 511 silver badge8 bronze badges 5
  • 1 Regex is likely the wrong way to acplish whatever you're trying to do with that. – Herohtar Commented Apr 17, 2018 at 15:53
  • What is a good way to acplish this? – Vishnu Murthy Commented Apr 17, 2018 at 15:53
  • 2 Sort your candidate and pare to the original (assuming that the original is already sorted like in your example). – PM 77-1 Commented Apr 17, 2018 at 15:55
  • I see you're doing a simple [1-4]+ – revo Commented Apr 17, 2018 at 15:57
  • 1 @VishnuMurthy Did any of the responses answer your question? – Jason Cust Commented Apr 24, 2018 at 19:14
Add a ment  | 

3 Answers 3

Reset to default 4

You may use this lookahead based assertions in your regex:

^(?!(?:[^1]*1){2})(?!(?:[^2]*2){2})(?!(?:[^3]*3){2})(?!(?:[^4]*4){2})[1234]+$

RegEx Demo

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 bination 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 bination 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 bination of 1, 2, 3, and 4 are matched, it also is matching numbers with repeating binations (e.g. 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 acplish 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:

  1. Loop over possible binations (a => s) (1, 123, 4321, etc.)
  2. Copy the current bination so as not to overwrite it (s2 = s)
  3. Loop over the characters of test string (x => ch) (1234 => 1, 2, 3, 4)
  4. Replace mon characters in the bination string shared with the test string (s2.replace)
    • For example in the bination 1, the 1 will be replaced when the loop gets to the character 1 in 1234 resulting in an empty string
  5. If the bination string's length reaches 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
发布评论

评论列表(0)

  1. 暂无评论