8

Let's say I have a string like "abcabcabc" and I want the positions of 'a's and 'b's swapped so that I end up with "bacbacbac". What is the most elegant solution for this? (For the sake of this question I hereby define 'elegant' as fast and readable.)

I came up with

"abcabcabc".replace( /[ab]/g, function( c ){ return { 'a': 'b', 'b': 'a' }[ c ] } )

Which I neither regard fast nor readable. But now I wonder if there is a better way of doing it?

EDIT: The characters can be at any position. So the answer should hold for "xyza123buvwa456" (would be then "xyzb123auvwb456", too.

EDIT2: "swap" seems to be the wrong word. Replace all of a with b and all of b with a while both are single characters.


I throw in a couple of other ones:

"abcabcabc".replace( 'a', '_' ).replace( 'b','a' ).replace( '_', 'b' )

"abcabcabc".replace( /[ab]/g, function( c ){ return "ba".charAt( c.charCodeAt()-'a'.charCodeAt() ); } )

"abcabcabc".replace( /[ab]/g, function( c ){ return "ab".charAt( "ba".indexOf( c ) ) } )

I ended up using a modified version of Mark C.'s Answer:

"abcabcabc".replace( /[ab]/g, c => c == 'a' ? 'b' : 'a' )
Daniel_Knights
  • 7,940
  • 4
  • 21
  • 49
Scheintod
  • 7,953
  • 9
  • 42
  • 61
  • So, how are you measuring performance that that code isn't fast? We need an object way to measure the answers or this is going to be opinion-based... – Heretic Monkey Feb 01 '18 at 20:46
  • 2
    So this looks more like you are just replacing `a` with `b` and `b` with `a` rather than swapping. Is that actually intentional, because it's not quite the same thing. For example `aaab` -> `bbba` if you just replace, whereas if you swap you might expect `baaa` (or `aaba` your rules on swapping aren't clear here) – Matt Burland Feb 01 '18 at 20:47
  • [How do I swap substrings within a string?](https://stackoverflow.com/q/7151466/215552) – Heretic Monkey Feb 01 '18 at 20:49
  • Possible duplicate of [How do I swap substrings within a string?](https://stackoverflow.com/questions/7151466/how-do-i-swap-substrings-within-a-string) – Mark C. Feb 01 '18 at 20:56
  • @Matt: You are right. See Edit2. – Scheintod Feb 01 '18 at 21:00
  • Mike/Mark: There is a significant difference between replacing single chars and whole strings. See my own edits/examples why this is not a duplicate. – Scheintod Feb 01 '18 at 21:44

5 Answers5

13

Try this :

str.replace(/[ab]/g, function($1) { return $1 === 'a' ? 'b' : 'a' })

example:

console.log("abcabcabc".replace(/[ab]/g, function($1) { return $1 === 'a' ? 'b' : 'a' }))
Mark C.
  • 6,332
  • 4
  • 35
  • 71
  • You don't need the pipe `|`. In fact, it shouldn't be there at all – Matt Burland Feb 01 '18 at 21:03
  • @MattBurland Got it - I was trying a myriad of different combinations and TBH have been trying to learn RegEx throug SO. Thanks for your help – Mark C. Feb 01 '18 at 21:07
  • Thanks. I ended up with a slightly modified version but I think this is both the cleanest and fastest way of doing it. (At least if not someone finds a sane way of doing it without regex.) – Scheintod Feb 01 '18 at 21:42
4

You can swap them (if they're always adjacent) by using a split/join combo:

console.log("abcabcabc".split("ab").join("ba"))

And in keeping with the split/join method, here's a way to swap them as individual characters (although it becomes significantly less readable):

console.log("aabbccaabbcc".split("a").map(s => s.split("b").join("a")).join("b"));
CRice
  • 29,968
  • 4
  • 57
  • 70
  • Thanks for your answer. I really like it's creative approach. But please see Edit. – Scheintod Feb 01 '18 at 21:01
  • @Scheintod I edited the answer with a way to swap non-adjacent characters, although I don't know if I'd recommend ever doing it that way (a regex replace is almost certainly more readable). – CRice Feb 01 '18 at 21:08
1

replace function accepts a string as the second parameter.

"abcabcabc".replace( /ab/g, "ba")

Leon Plata
  • 622
  • 5
  • 9
1

I use this method when I need to swap long list of characters\words\strings!

The method also prevents strings already replaced to be replaced again, Example:

String = "AAABBBCCC BBB"

Replace "AAABBBCCC" with "BBB", then, "BBB" with "DDD"

Final String = "BBB DDD"

Note that, only "BBB" from the original string is replaced to "DDD"! The "BBB" replaced from "AAABBBCCC" is not re-replaced to "DDD"!

User
  • 71
  • 1
  • 7
0

Use a direct replace using Regex:

var result = "abcabcabc".replace( /ab/g, "ba");
console.log(result);
Ele
  • 33,468
  • 7
  • 37
  • 75