Removing items using Array.map in JavaScript

I would like to filter an array of elements using the map() function. Here is the code snippet:

 var filteredItems = items.map(function(item) { if( ...some condition... ) { return item; } }); 

The problem is that the filtered elements still use the space in the array, and I would like to completely destroy them.

Any idea?

EDIT: Thanks, I forgot about filter() , I would actually like filter() , and then map() .

EDIT2: Thanks for pointing out that map() and filter() not implemented in all browsers, although my special code is not designed to run in a browser.

+71
javascript client-side functional-programming data-manipulation
Aug 12 '08 at 22:21
source share
6 answers

You should use the filter method, not the map, if you don't want to mutate the elements in the array, in addition to filtering.

eg.

 var filteredItems = items.filter(function(item) { return ...some condition...; }); 

[Edit: Of course, you can always make sourceArray.filter(...).map(...) to filter and mutate]

+90
Aug 12 '08 at
source share

I wrote an answer a while ago, and my opinion has changed. I recommend checking out my blog post that extends this topic and explains it much better. It also gives a JSperf comparison at the end of alternatives.

Tl; dr is this: to accomplish what you ask for (filtering and displaying within a single function call), you must use Array.reduce() . However, a more readable and usually faster 2 approach is to simply use a filter and the cards are connected to each other:

[1,2,3].filter(num => num > 2).map(num => num * 2)

The following is a description of how Array.reduce() works, and how it can be used to perform filtering and matching in one iteration. If this is too concise, I highly recommend looking at the blog post linked above, which is a much more friendly introduction with clear examples and progress.

You give to reduce the argument, which is a (usually anonymous) function.

This anonymous function takes two parameters - one (like the anonymous functions passed to map / filter / forEach) is the iterator you need to work with. However, for the anonymous function, another argument is passed, namely that these functions are not accepted, and this is the value that will be passed between function calls, often called a reminder .

Note that while Array.filter () takes only one argument (function), Array.reduce () also takes an important (albeit optional) second argument: the initial value for memo, which will be passed to this anonymous function as its first argument, and then can be mutated and passed between function calls. (If it is not specified, then by default “memo” in the first call of the anonymous function will be the first iterator, and the argument of the “iterator” will actually be the second value in the array)

In our case, we will pass an empty array to run, and then choose whether to insert our iterator into our array or not based on our function - this is a filtering process.

Finally, we will return our “array in process” with every call to the anonymous function, and Reduce will take this return value and pass it as an argument (called memo) to the next function call.

This allows you to filter and display the map in one iteration, halving the number of necessary iterations. :)

For a more complete explanation, refer to MDN or the link above. :)

A basic example of calling Reduce:

 let array = [1,2,3]; const initialMemo = []; array = array.reduce((memo, iteratee) => { // if condition is our filter if (iteratee > 1) { // what happens inside the filter is the map memo.push(iteratee * 2); } // this return value will be passed in as the 'memo' argument // to the next call of this function, and this function will have // every element passed into it at some point. return memo; }, initialMemo) console.log(array) // [4,6], equivalent to [(2 * 2), (3 * 2)] 

shorter version:

 [1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, []) 

Please note that the first iterable was no more than one and therefore was filtered. Also pay attention to initialMemo, named simply to clarify its existence and draw attention to it. Once again, it is passed as a “reminder” to the first call of the anonymous function, and then the return value of the anonymous function is passed as the argument of the “note” to the next function.

Another example of the classic use case for memo is to return the smallest or largest number in an array. Example:

 [7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val) // ^this would return the largest number in the list. 

An example of how to write your own cast function (this often helps to understand functions like these, I find):

 test_arr = []; // we accept an anonymous function, and an optional 'initial memo' value. test_arr.my_reducer = function(reduceFunc, initialMemo) { // if we did not pass in a second argument, then our first memo value // will be whatever is in index zero. (Otherwise, it will // be that second argument.) const initialMemoIsIndexZero = arguments.length < 2; // here we use that logic to set the memo value accordingly. let memo = initialMemoIsIndexZero ? this[0] : initialMemo; // here we use that same boolean to decide whether the first // value we pass in as iteratee is either the first or second // element const initialIteratee = initialMemoIsIndexZero ? 1 : 0; for (var i = initialIteratee; i < this.length; i++) { // memo is either the argument passed in above, or the // first item in the list. initialIteratee is either the // first item in the list, or the second item in the list. memo = reduceFunc(memo, this[i]); } // after we've compressed the array into a single value, // we return it. return memo; } 

The actual implementation allows you to access things like the index, for example, but I hope this helps you easily understand the point.

+33
Apr 11 '16 at 19:25
source share

This is not what the map does. Do you really want Array.filter . If you really want to remove items from the original list, you will need to do this with a for loop.

+10
Aug 12 '08 at 22:33
source share
 var arr = [1,2,'xxx','yyy'] // ES5 syntax arr = arr.filter(function(item){ return item != 'xxx' }); // ES2015 syntax arr = arr.filter(item => item != 'xxx'); arr // [1, 2, "yyy"] 
+5
Sep 30 '09 at 14:56
source share

I am posting this answer here because the polyfields shared on this page are terrible

 function reduce(f, y, xs, context) { var acc = y; for (var i = 0, len = xs.length; i < len; i++) acc = f.call(context, acc, xs[i], i, xs); return acc; } function reduce1(f, xs, context) { if (xs.length === 0) throw Error('cannot reduce empty array without initial value'); else return reduce(f, xs[0], xs.slice(1), context); } function map(f, xs, context) { return reduce(function(acc, x, i) { return acc.concat([ f.call(context, x, i, xs) ]); }, [], xs); } function filter(f, xs, context) { return reduce(function(acc, x, i) { if (f.call(context, x, i, xs)) return acc.concat([x]); else return acc; }, [], xs); } 

extend prototypes

 if (Array.prototype.reduce === undefined) { Array.prototype.reduce = function(f, initialValue, context) { if (initialValue === undefined) return reduce1(f, this, context); else return reduce(f, initialValue, this, context); }; } if (Array.prototype.map === undefined) { Array.prototype.map = function(f, context) { return map(f, this, context); }; } if (Array.prototype.filter === undefined) { Array.prototype.filter = function(f, context) { return filter(f, this, context); }; } 
+3
Sep 23 '16 at 17:00
source share

However, you should note that Array.filter not supported in all browsers, so you should prototype:

 //This prototype is provided by the Mozilla foundation and //is distributed under the MIT license. //http://www.ibiblio.org/pub/Linux/LICENSES/mit.license if (!Array.prototype.filter) { Array.prototype.filter = function(fun /*, thisp*/) { var len = this.length; if (typeof fun != "function") throw new TypeError(); var res = new Array(); var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in this) { var val = this[i]; // in case fun mutates this if (fun.call(thisp, val, i, this)) res.push(val); } } return res; }; } 

And while you can prototype any method that you may need.

+2
Aug 12 '08 at 23:44
source share



All Articles