Reputation: 9622
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?
Upvotes: 104
Views: 133644
Reputation: 66355
Or this can be solved with arrow functions:
trimmed_x = x.map(s => s.trim());
Upvotes: 155
Reputation: 1282
x = [' aa ', ' bb ', 'cccc '].toString().replace(/\s*\,\s*/g, ",").trim().split(",");
console.log(x)
Upvotes: 1
Reputation: 1055
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())
Upvotes: 41
Reputation: 89
### 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"]
Upvotes: -3
Reputation: 3913
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']
Upvotes: -2
Reputation: 47
Keep it simple and stupid:
[' aa ', ' b b ', ' c c '].map(i=>i.trim());
["aa", "b b", "c c"]
Upvotes: 3
Reputation: 5159
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.
Upvotes: 1
Reputation: 26161
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))
Upvotes: 3
Reputation: 46750
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);
Upvotes: 28
Reputation: 33408
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 ;)
Upvotes: 5
Reputation: 664599
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 this
Arg - 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
Upvotes: 109
Reputation: 382160
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.
Upvotes: 19