Javascript - Apply trim function to each string in an array

JavascriptFunctionTrim

Javascript Problem Overview


Want to trim each string in an array, e.g., given

x = [' aa ', ' bb '];

output

['aa', 'bb']
 

My first trial is

x.map(String.prototype.trim.apply)

It got "TypeError: Function.prototype.apply was called on undefined, which is a undefined and not a function" in chromium.

Then I tried

x.map(function(s) { return String.prototype.trim.apply(s); });

It works. What's the difference?

Javascript Solutions


Solution 1 - Javascript

Or this can be solved with arrow functions:

x.map(s => s.trim());

Solution 2 - Javascript

String.prototype.trim.apply is the Function.prototype.apply method without being bound to trim. map will invoke it with the string, the index and the array as arguments and nothing (undefined) for the thisArg - however, apply expects to be called on functions:

var apply = String.prototype.trim.apply;
apply.call(undefined, x[0], 0, x) // TypeError

What you can do is passing the trim function as the context for call:

[' aa ', ' bb '].map(Function.prototype.call, String.prototype.trim)
// ['aa', 'bb']

What happens here is

var call = Function.prototype.call,
    trim = String.prototype.trim;
call.call(trim, x[0], 0, x) ≡
      trim.call(x[0], 0, x) ≡
            x[0].trim(0, x); // the arguments don't matter to trim

Solution 3 - Javascript

The simple variant without dependencies:

 for (var i = 0; i < array.length; i++) {
     array[i] = array[i].trim()
 }

ES6 variant:

const newArray = oldArray.map(string => string.trim())

ES6 function variant:

const trimmedArray = array => array.map(string => string.trim())

Solution 4 - Javascript

If you are using JQuery, then a better way to do this, as it will work with IE8 as well (I need to support IE8) is this:

$.map([' aa ', ' bb ', '   cc '], $.trim);

Solution 5 - Javascript

First, do it simply :

x.map(function(s) { return s.trim() });

Then, the reason why the first one doesn't work is that the string is passed as argument to the callback, not as context. As you pass no argument to apply, you get the same message you would have got with

var f = String.prototype.trim.apply; f.call();

Now, mostly for fun, let's suppose you're not happy with the fact that map use the callback this way and you'd want to be able to pass a function using the context, not the argument.

Then you could do this :

Object.defineProperty(Array.prototype, "maprec", {
  value: function(cb){
      return this.map(function(v){ return cb.call(v) })
  }
});
console.log([' aa ', ' bb '].maprec(String.prototype.trim)); // logs ["aa", "bb"]

I said "mostly for fun" because modifying objects you don't own (Array's prototype here) is widely seen as a bad practice. But you could also make a utilitarian function taking both the array and the callback as arguments.

Solution 6 - Javascript

I just compared some ways to trim an array of strings to get the shortest and fastest method. Who is interested in, here is a performance test on jsperf: http://jsperf.com/trim-array-of-strings

var chunks = "  .root  ,  .parent  >  .child  ".split(',')
var trimmed1 = chunks.map(Function.prototype.call, String.prototype.trim);
var trimmed2 = chunks.map(function (str) { return str.trim(); });
var trimmed3 = chunks.map(str => str.trim());
var trimmed4 = $.map(chunks, $.trim);

Note: jQuery is just here to compare the number of characters to type ;)

Solution 7 - Javascript

Keep it simple and stupid:

Code

[' aa ', ' b b ', '   c c '].map(i=>i.trim());
Output

["aa", "b b", "c c"]

Solution 8 - Javascript

Influencing from Bergi's perfect answer, i just would like to add, for those methods which won't take a this argument, you may achieve the same job as follows;

var x = [' aa ', ' bb '],
    y = x.map(Function.prototype.call.bind(String.prototype.trim))

Solution 9 - Javascript

var x = [" aa ", " bb "];
console.log(x); // => [" aa ", " bb "]

// remove whitespaces from both sides of each value in the array
x.forEach(function(value, index){
  x[index] = value.trim();
});

console.log(x); // => ["aa", "bb"]

All major browsers support forEach(), but note that IE supports it only beginning from version 9.

Solution 10 - Javascript

x = [' aa ', ' bb ', 'cccc '].toString().replace(/\s*\,\s*/g, ",").trim().split(",");

console.log(x)

Solution 11 - Javascript

    ### Code
    <!-- language: lang-js -->
    
     var x=  [' aa ', ' b b ', '   c c ']
var x = x.split(",");
			x = x.map(function (el) {
				return el.trim();
                console.log(x)
        
    ### Output
    <!-- language: lang-none -->
        ["aa", "b b", "c c"]     

Solution 12 - Javascript

Another ES6 alternative

const row_arr = ['a ', ' b' , ' c ', 'd'];
const trimed_arr = row_arr.map(str => str.trim());
console.log(trimed_arr); // <== ['a', 'b', 'c', 'd']

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionneurontView Question on Stackoverflow
Solution 1 - JavascriptDominicView Answer on Stackoverflow
Solution 2 - JavascriptBergiView Answer on Stackoverflow
Solution 3 - JavascriptmusemindView Answer on Stackoverflow
Solution 4 - JavascriptSachin KainthView Answer on Stackoverflow
Solution 5 - JavascriptDenys SéguretView Answer on Stackoverflow
Solution 6 - JavascriptyckartView Answer on Stackoverflow
Solution 7 - JavascriptMartín SilvaView Answer on Stackoverflow
Solution 8 - JavascriptReduView Answer on Stackoverflow
Solution 9 - JavascriptAmrView Answer on Stackoverflow
Solution 10 - JavascriptSurojit PaulView Answer on Stackoverflow
Solution 11 - Javascriptkoteswararao pvView Answer on Stackoverflow
Solution 12 - JavascriptgildniyView Answer on Stackoverflow