user2686830
user2686830

Reputation: 7

Regular expression that remove second occurrence of a character in a string

I'm trying to write a JavaScript function that removes any second occurrence of a character using the regular expression. Here is my function

var removeSecondOccurrence = function(string) {
return string.replace(/(.*)\1/gi, '');
}

It's only removing consecutive occurrence. I'd like it to remove even non consecutive one. for example papirana should become pairn.

Please help

Upvotes: 0

Views: 7689

Answers (4)

georg
georg

Reputation: 214969

A non-regexp solution:

 "papirana".split("").filter(function(x, n, self) { return self.indexOf(x) == n }).join("")

Regexp code is complicated, because JS doesn't support lookbehinds:

str = "papirana";
re = /(.)(.*?)\1/;
while(str.match(re)) str = str.replace(re, "$1$2")

or a variation of the first method:

"papirana".replace(/./g, function(a, n, str) { return str.indexOf(a) == n ? a : "" })

Upvotes: 4

Amadan
Amadan

Reputation: 198324

What Michelle said.

In fact, I strongly suspect it cannot be done using regular expressions. Or rather, you can if you reverse the string, remove all but the first occurences, then reverse again, but it's a dirty trick and what Michelle suggests is way better (and probably faster).

If you're still hot on regular expressions...

"papirana".
    split("").
    reverse().
    join("").
    replace(/(.)(?=.*\1)/g, '').
    split("").
    reverse().
    join("")

// => "pairn"

The reason why you can't find all but the first occurence without all the flippage is twofold:

  • JavaScript does not have lookbehinds, only lookaheads
  • Even if it did, I don't think any regexp flavour allows variable-length lookbehinds

Upvotes: 0

6502
6502

Reputation: 114491

Using a zero-width lookahead assertion you can do something similar

"papirana".replace(/(.)(?=.*\1)/g, "")

returns

"pirna"

The letters are of course the same, just in a different order.

Passing the reverse of the string and using the reverse of the result you can get what you're asking for.

Upvotes: 2

Michelle
Michelle

Reputation: 2900

This is how you would do it with a loop:

var removeSecondOccurrence = function(string) {
    var results = "";
    for (var i = 0; i < string.length; i++)
        if (!results.contains(string.charAt(i)))
            results += string.charAt(i);
}

Basically: for each character in the input, if you haven't seen that character already, add it to the results. Clear and readable, at least.

Upvotes: 0

Related Questions