How do I split a string with multiple separators in JavaScript?

Viewed 749682

How do I split a string with multiple separators in JavaScript?

I'm trying to split on both commas and spaces, but AFAIK JavaScript's split() function only supports one separator.

25 Answers

Pass in a regexp as the parameter:

js> "Hello awesome, world!".split(/[\s,]+/)
Hello,awesome,world!

Edited to add:

You can get the last element by selecting the length of the array minus 1:

>>> bits = "Hello awesome, world!".split(/[\s,]+/)
["Hello", "awesome", "world!"]
>>> bit = bits[bits.length - 1]
"world!"

... and if the pattern doesn't match:

>>> bits = "Hello awesome, world!".split(/foo/)
["Hello awesome, world!"]
>>> bits[bits.length - 1]
"Hello awesome, world!"

You can pass a regex into JavaScript's split() method. For example:

"1,2 3".split(/,| /) 
["1", "2", "3"]

Or, if you want to allow multiple separators together to act as one only:

"1, 2, , 3".split(/(?:,| )+/) 
["1", "2", "3"]

You have to use the non-capturing (?:) parenthesis, because otherwise it gets spliced back into the result. Or you can be smart like Aaron and use a character class.

Examples tested in Safari and Firefox.

I'm suprised no one has suggested it yet, but my hack-ey (and crazy fast) solution was to just append several 'replace' calls before splitting by the same character.

i.e. to remove a, b, c, d, and e:

let str = 'afgbfgcfgdfgefg'
let array = str.replace('a','d').replace('b','d').replace('c','d').replace('e','d').split('d')

this can be conveniently generalized for an array of splitters as follows:

function splitByMany( manyArgs, string ) {
  do {
    let arg = manyArgs.pop()
    string = string.replace(arg, manyArgs[0])
  } while (manyArgs.length > 2)
  return string.split(manyArgs[0])
}

So, in your case, you could then call

let array = splitByMany([" ", ","], 'My long string containing commas, and spaces, and more commas');

Here are some cases that may help by using Regex:

  • \W to match any character else word character [a-zA-Z0-9_]. Example:
("Hello World,I-am code").split(/\W+/); // would return [ 'Hello', 'World', 'I', 'am', 'code' ]
  • \s+ to match One or more spaces
  • \d to match a digit
  • if you want to split by some characters only let us say , and - you can use str.split(/[,-]+/)...etc

My refactor of @Brian answer

var string = 'and this is some kind of information and another text and simple and some egample or red or text';
var separators = ['and', 'or'];

function splitMulti(str, separators){
            var tempChar = 't3mp'; //prevent short text separator in split down
            
            //split by regex e.g. \b(or|and)\b
            var re = new RegExp('\\b(' + separators.join('|') + ')\\b' , "g");
            str = str.replace(re, tempChar).split(tempChar);
            
            // trim & remove empty
            return str.map(el => el.trim()).filter(el => el.length > 0);
}

console.log(splitMulti(string, separators))

Here is a new way to achieving same in ES6:

function SplitByString(source, splitBy) {
  var splitter = splitBy.split('');
  splitter.push([source]); //Push initial value

  return splitter.reduceRight(function(accumulator, curValue) {
    var k = [];
    accumulator.forEach(v => k = [...k, ...v.split(curValue)]);
    return k;
  });
}

var source = "abc,def#hijk*lmn,opq#rst*uvw,xyz";
var splitBy = ",*#";
console.log(SplitByString(source, splitBy));

Please note in this function:

  • No Regex involved
  • Returns splitted value in same order as it appears in source

Result of above code would be:

enter image description here

I will provide a classic implementation for a such function. The code works in almost all versions of JavaScript and is somehow optimum.

  • It doesn't uses regex, which is hard to maintain
  • It doesn't uses new features of JavaScript
  • It doesn't uses multiple .split() .join() invocation which require more computer memory

Just pure code:

var text = "Create a function, that will return an array (of string), with the words inside the text";

println(getWords(text));

function getWords(text)
{
    let startWord = -1;
    let ar = [];

    for(let i = 0; i <= text.length; i++)
    {
        let c = i < text.length ? text[i] : " ";

        if (!isSeparator(c) && startWord < 0)
        {
            startWord = i;
        }

        if (isSeparator(c) && startWord >= 0)
        {
            let word = text.substring(startWord, i);
            ar.push(word);

            startWord = -1;
        }
    }

    return ar;
}

function isSeparator(c)
{
    var separators = [" ", "\t", "\n", "\r", ",", ";", ".", "!", "?", "(", ")"];
    return separators.includes(c);
}

You can see the code running in playground: https://codeguppy.com/code.html?IJI0E4OGnkyTZnoszAzf

Splitting URL by .com/ or .net/

url.split(/\.com\/|\.net\//)
a = "a=b,c:d"

array = ['=',',',':'];

for(i=0; i< array.length; i++){ a= a.split(array[i]).join(); }

this will return the string without a special charecter.

Not the best way but works to Split with Multiple and Different seperators/delimiters

html

<button onclick="myFunction()">Split with Multiple and Different seperators/delimiters</button>
<p id="demo"></p>

javascript

<script>
function myFunction() {

 var str = "How : are | you doing : today?";
 var res = str.split(' | ');

 var str2 = '';
 var i;
 for (i = 0; i < res.length; i++) { 
    str2 += res[i];
    
    if (i != res.length-1) {
      str2 += ",";
    }
 }
 var res2 = str2.split(' : ');

 //you can add countless options (with or without space)

 document.getElementById("demo").innerHTML = res2;
}
</script>

I solved this with reduce and filter. It might not be the most readable solution, or the fastest, and in real life I would probably use Aarons answere here, but it was fun to write.

[' ','_','-','.',',',':','@'].reduce(
(segs, sep) => segs.reduce(
(out, seg) => out.concat(seg.split(sep)), []), 
['E-mail Address: user@domain.com, Phone Number: +1-800-555-0011']
).filter(x => x)

Or as a function:

function msplit(str, seps) {
  return seps.reduce((segs, sep) => segs.reduce(
    (out, seg) => out.concat(seg.split(sep)), []
  ), [str]).filter(x => x);
}

This will output:

['E','mail','Address','user','domain','com','0','Phone','Number','+1','800','555','0011']

Without the filter at the end you would get empty strings in the array where two different separators are next to each other.

I ran into this question wile looking for a replacement for the C# string.Split() function which splits a string using the characters in its argument.

In JavaScript you can do the same using map an reduce to iterate over the splitting characters and the intermediate values:

let splitters = [",", ":", ";"]; // or ",:;".split("");
let start= "a,b;c:d";
let values = splitters.reduce((old, c) => old.map(v => v.split(c)).flat(), [start]);
// values is ["a", "b", "c", "d"]

flat() is used to flatten the intermediate results so each iteration works on a list of strings without nested arrays. Each iteration applies split to all of the values in old and then returns the list of intermediate results to be split by the next value in splitters. reduce() is initialized with an array containing the initial string value.

Check out my simple library on Github

If you really do not want to visit or interact with the repo, here is the working code:

/**
 * 
 * @param {type} input The string input to be split
 * @param {type} includeTokensInOutput If true, the tokens are retained in the splitted output.
 * @param {type} tokens The tokens to be employed in splitting the original string.
 * @returns {Scanner}
 */
function Scanner(input, includeTokensInOutput, tokens) {
    this.input = input;
    this.includeTokensInOutput = includeTokensInOutput;
    this.tokens = tokens;
}

Scanner.prototype.scan = function () {
    var inp = this.input;

    var parse = [];
    this.tokens.sort(function (a, b) {
        return b.length - a.length; //ASC, For Descending order use: b - a
    });
    for (var i = 0; i < inp.length; i++) {


        for (var j = 0; j < this.tokens.length; j++) {

            var token = this.tokens[j];
            var len = token.length;
            if (len > 0 && i + len <= inp.length) {
                var portion = inp.substring(i, i + len);
                if (portion === token) {
                    if (i !== 0) {//avoid empty spaces
                        parse[parse.length] = inp.substring(0, i);
                    }
                    if (this.includeTokensInOutput) {
                        parse[parse.length] = token;
                    }
                    inp = inp.substring(i + len);
                    i = -1;
                    break;
                }

            }

        }

    }
    if (inp.length > 0) {
          parse[parse.length] = inp;
    }

    return parse;


};

The usage is very straightforward:

    var tokens = new Scanner("ABC+DE-GHIJK+LMNOP", false , new Array('+','-')).scan();

console.log(tokens); 

Gives:

['ABC', 'DE', 'GHIJK', 'LMNOP']

And if you wish to include the splitting tokens (+ and -) in the output, set the false to true and voila! it still works.

The usage would now be:

var tokens = new Scanner("ABC+DE-GHIJK+LMNOP", true , new Array('+','-')).scan();

and

console.log(tokens);

would give:

['ABC', '+', 'DE', '-', 'GHIJK', '+', 'LMNOP']

ENJOY!

Related