There are many ways to implement the array filter function, some people have counted in JS at least 10 ways.

This article is concerned with: can use the re to achieve the function of weight filtering?

Admittedly, even if it were possible, no one would consider it a best practice.

So here, we’re just thinking about possibilities.

The answer: Yes! And in more ways than one.

Let’s take a step-by-step look at how this is done, from easy to difficult.

1. Adjacency character filtering problem

“abbccc” => “abc”

A backreference is used in a re to match a previously occurring character:

function distinct(string) {
  returnstring.replace(/(.) \1+/g,'$1')
}
console.log(distinct("abbccc")) / / = >"abc"
Copy the code

Where \1 is a backreference to the data captured by the first parenthesis, called (.) Group for capture. And $1 also represents the data captured by the first bracket. See the figure below for details.

Blue indicates the data captured by the capture group, and pink indicates the data referred to by backreference. After the replacement, only blue data is retained.

2. String weight filtering

“abbacbc” => “abc”

Methods a

What about a normal string?

The most straightforward idea is to turn a problem into a solved problem.

Split the string into arrays, then bytecode sorting, into adjacent character filtering problem.

This way, with the array correlation method, the regular flavor is not so strong.

Way 2

Use loops to remove recurring characters.

function distinct(string){
  while(/ (.). . *? \1/.test(string)) { string = string.replace(/(.) (. *?) 1 \ /,'$1 $2')}return string;
}
console.log(distinct("abbacbc")) / / = >"abc"
Copy the code

With regular/(.). . *? \1/ to determine if there are any duplicate characters in the string, and replace them if there are. The regular for the substitution is /(.). (. *?) \1/, where two sets of parentheses are used to provide data for referencing $1 and $2. The specific process is shown as follows:

Methods three

Method 2 uses a loop, which feels a little silly. You can just use replace. You need to use (? = p) :

function distinct(string) {
  returnstring.replace(/(.) (? = (. *? \1)/g,' ')
}
console.log(distinct("abbacbc")) / / = >"abc"
Copy the code

The specific process is shown as follows:

(? = (. *? \1) represents the matching position, as shown by the green arrow in the figure. For example, the position after the character a in the first line matches.*? \1, where \1 is the pink data in the figure, corresponding to the blue data captured in the first group. Finally all the blue data is replaced with ”.

One problem with this implementation is that repeated characters retain only the last character to occur. If you add an “A” to the original string to make it “abbacbca”, the result is “bCA”.

Methods four

The third idea is to see if the current character appears later, and if so, delete it. The logic of option 4 is reversed: if the current character appears before it, delete it. An assertion (? <=p) to see if the current position matches p.

Re cannot be written as /(? < = (. *? \ 1) (.). /g, because \1 is a “reverse” reference, only the grouping before it can be referenced. So here we put it after the target character:

function distinct(string) {
  returnstring.replace(/(.) (? < = \ 1. *? \1)/g,' ')
}
console.log(distinct("abbacbc")) / / = >"abc"
Copy the code

The specific process is as follows:

(? < = \ 1. *? \ 1)
\ 1
b

3. Array filter weight

With string filtering, array filtering is easy. All four methods can be written in the array version. For example, the fourth option is as follows:

function distinct(arr) {
  return arr.join(' ').replace(/(.) (? < = \ 1. *? \1)/g,' ').split(' ')
}
console.log(distinct(['a'.'b'.'b'.'a'.'c'.'b'.'c'/ / = > []))'a'.'b'.'c']
Copy the code

There are a few problems with our solution so far:

  • You can only filter if each element of the array is one character
  • The result of filtering is to convert elements to characters.

Supporting multiple characters is relatively easy to solve, but to preserve types, you need JSON for both methods.

Finally, the final version of scheme 4 is given:

functiondistinct(arr) { var string = JSON.stringify(arr) string = string.replace(/,([^,]+)(? < = \ 1. *? (\ 1)? =,|])/g, (m,The $1) = >The $1= ='"' ? m : ' ')
  return JSON.parse(string)
}
console.log(distinct(["aa", 1,"ab".true, 1,true."aa"/ / = > []))"aa", 1, "ab".true]
Copy the code

In this paper, to the end.

In addition, welcome to read my JS regular mini book.