56

I am trying to explode an string using javascript to pick searchterms, whitespace-separated. However I get empty array elements if a searchterm is ended by a whitespace, as shown below.

What should I do instead to avoid post-processing this array and removing empty elements?

var str = "searchterm1 searchterm2";
console.log(str.split(" ")); // ["searchterm1", "searchterm2"]

var strb = "searchterm1 "; // Note the ending whitespace
console.log(strb.split(" ")); // ["searchterm1", ""]
I. J. Kennedy
  • 24,725
  • 16
  • 62
  • 87
Industrial
  • 41,400
  • 69
  • 194
  • 289
  • 2
    regarding this old question. you just add `.filter(e => e)` on the end of the split, to eliminate empty items. this is typical when you split on newlines. – Fattie Aug 10 '21 at 13:08

6 Answers6

82

You could simply match all non-space character sequences:

str.match(/[^ ]+/g)
Gumbo
  • 643,351
  • 109
  • 780
  • 844
60

No matter what splitter this always works:

str.split(' ').filter(function(i){return i})
// With ES6
str.split(' ').filter(i => i)

Filter logic also can change in some other cases.

user1079877
  • 9,008
  • 4
  • 43
  • 54
  • 2
    Do you know, **why** this works? Documentation says `filter()` method creates a new array with all elements that pass the test implemented by the provided function. In this case empty elements seem to be ignored by this method and therefore aren't in the resulting array. I don't understand why this test isn't done for empty elements. – Frébo Oct 12 '16 at 06:05
  • 14
    Answer is simple, if you have more than one space character, you'll have empty string ('') in your results, and because `if('')` is false, `filter` function filter strip them in the final result. – user1079877 Oct 13 '16 at 08:24
  • 1
    If you want your filter function to return a boolean value instead of a string (although this is surprisingly not a problem, even with Typescript), you can also do `str.split(' ').filter(Boolean)` – Hart Simha Apr 28 '21 at 06:19
17

This is a bit old, but for documentation purposes there is also another neat way.

someString.filter(Boolean);

// Example
['fds', '', 'aaaaa', 'AA', 'ffDs', "", 'd'].filter(Boolean);
// Output
["fds", "aaaaa", "AA", "ffDs", "d"]

Edit

How does it work ?

The following are identical

.filter(Boolean)
.filter((value) => Boolean(value))

Boolean() as function behave as a converter of any type to Boolean by the standard input to output.

References:
Global Objects -> Boolean
Truthy
Falsy

Orel Eraki
  • 11,940
  • 3
  • 28
  • 36
  • How does this work? – AlwaysLearning Nov 02 '21 at 11:23
  • 1
    It works because JavaScript consider an empty string (length is 0) as false. https://stackoverflow.com/questions/8692982/in-javascript-is-an-empty-string-always-false-as-a-boolean#:~:text=58-,Yes.,false%20%3B%20everything%20else%20is%20true%20. – Orel Eraki Nov 02 '21 at 12:36
  • 1
    I meant to ask: what does `Boolean` mean as argument? – AlwaysLearning Nov 03 '21 at 15:56
  • 2
    Ok, First, we need to understand that these two are identical `.filter(Boolean)` is equal to `.filter((value) => Boolean(value))`. Now that is out of the way, `Boolean()` as function behave as a converter of any type to Boolean. Read https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean#description In Addition to https://developer.mozilla.org/en-US/docs/Glossary/Truthy and https://developer.mozilla.org/en-US/docs/Glossary/Falsy – Orel Eraki Nov 06 '21 at 07:48
  • Thank you. IMO this needs to be part of the reply. – AlwaysLearning Nov 06 '21 at 16:42
  • @AlwaysLearning, you are right, I've edited the answer. – Orel Eraki Nov 08 '21 at 09:16
2

This is the simplest solution IMO. trim() first to get rid of leading/trailing whitespace, then split by whitespace.

function split(str) {
  return str.trim().split(/\s+/);
}

console.log(split('foo bar baz'));
console.log(split('  foo  bar  baz '));
Yangshun Tay
  • 49,270
  • 33
  • 114
  • 141
1

If you want a function that you can use, just extend String:

 String.prototype.splitNoSpaces = function(){
     return this.split(' ').filter(function(i){return i});
 };

 //Now use it!
 var classString = "class1    class2 class3    class4";
 var classArray = classString.splitNoSpaces();

 //classArray[0] is class1
 //classArray[1] is class2
 //classArray[2] is class3
 //classArray[3] is class4

Thanks to @user1079877 for the hint

Chris Sprague
  • 3,158
  • 33
  • 24
0

Add function:

//Some browsers support trim so we check for that first
if(!String.prototype.trim) {  
  String.prototype.trim = function () {  
    return this.replace(/^\s+|\s+$/g,'');  
  };  
}

Then call trim on the string:

var strb = "searchterm1 "; // Note the ending whitespace
console.log(strb.trim().split(" ")); // ["searchterm1"]
Stig Hausberg
  • 836
  • 6
  • 9