Je voudrais filtrer un tableau d'éléments en utilisant la map()
fonction. Voici un extrait de code:
var filteredItems = items.map(function(item)
{
if( ...some condition... )
{
return item;
}
});
Le problème est que les éléments filtrés utilisent toujours de l'espace dans le tableau et je voudrais les effacer complètement.
Une idée?
EDIT: Merci, j'ai oublié filter()
, ce que je voulais, c'est en fait un filter()
alors un map()
.
EDIT2: Merci d'avoir indiqué cela map()
et filter()
ne sont pas implémentés dans tous les navigateurs, bien que mon code spécifique ne soit pas destiné à fonctionner dans un navigateur.
javascript
functional-programming
data-manipulation
client-side
Vincent Robert
la source
la source
Réponses:
Vous devez utiliser la
filter
méthode plutôt que le mappage, sauf si vous souhaitez muter les éléments du tableau, en plus du filtrage.par exemple.
var filteredItems = items.filter(function(item) { return ...some condition...; });
[Modifier: bien sûr, vous pouvez toujours faire
sourceArray.filter(...).map(...)
pour filtrer et muter]la source
map
ne mute pasmap
.x=[1,2,3];y = x.map(z => z*2);console.log(x,y);
Inspiré par la rédaction de cette réponse, j'ai fini par développer plus tard et écrire un article de blog sur ce sujet en détail. Je vous recommande de vérifier cela si vous souhaitez développer une compréhension plus profonde de la façon de penser à ce problème - j'essaie de l'expliquer pièce par pièce et je donne également une comparaison JSperf à la fin, en passant en revue les considérations de vitesse.
Cela dit, le tl; dr est le suivant: pour accomplir ce que vous demandez (filtrage et mappage dans un seul appel de fonction), vous utiliseriez
Array.reduce()
.Cependant, l' approche la plus lisible et (moins important) généralement beaucoup plus rapide 2 consiste simplement à utiliser un filtre et une carte enchaînés ensemble:
[1,2,3].filter(num => num > 2).map(num => num * 2)
Ce qui suit est une description de son
Array.reduce()
fonctionnement et de la manière dont il peut être utilisé pour effectuer un filtre et une carte en une seule itération. Encore une fois, si cela est trop condensé, je recommande vivement de consulter le billet de blog lié ci-dessus, qui est une intro beaucoup plus conviviale avec des exemples clairs et une progression.Vous donnez à réduire un argument qui est une fonction (généralement anonyme).
Cette fonction anonyme prend deux paramètres - l'un (comme les fonctions anonymes transmises à map / filter / forEach) est l'itéré à utiliser. Il existe un autre argument pour la fonction anonyme transmise pour réduire, cependant, que ces fonctions n'acceptent pas, et c'est la valeur qui sera transmise entre les appels de fonction, souvent appelée mémo .
Notez que si Array.filter () ne prend qu'un seul argument (une fonction), Array.reduce () prend également un deuxième argument important (bien que facultatif): une valeur initiale pour 'memo' qui sera passée dans cette fonction anonyme comme premier argument, et peut ensuite être muté et transmis entre les appels de fonction. (S'il n'est pas fourni, alors 'memo' dans le premier appel de fonction anonyme sera par défaut le premier iteratee, et l'argument 'iteratee' sera en fait la deuxième valeur du tableau)
Dans notre cas, nous passerons un tableau vide pour commencer, puis choisirons d'injecter ou non notre iteratee dans notre tableau en fonction de notre fonction - c'est le processus de filtrage.
Enfin, nous retournerons notre 'tableau en cours' à chaque appel de fonction anonyme, et reduction prendra cette valeur de retour et la transmettra comme argument (appelé mémo) à son prochain appel de fonction.
Cela permet au filtre et à la carte de se produire en une seule itération, réduisant de moitié le nombre d'itérations requises - en effectuant simplement deux fois plus de travail à chaque itération, cependant, rien n'est vraiment enregistré à part les appels de fonction, qui ne sont pas si chers en javascript .
Pour une explication plus complète, reportez-vous à la documentation MDN (ou à mon article référencé au début de cette réponse).
Exemple de base d'un appel de réduction:
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)]
version plus succincte:
[1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])
Notez que la première itération n'était pas supérieure à un, et a donc été filtrée. Notez également le initialMemo, nommé juste pour rendre son existence claire et attirer l'attention sur lui. Encore une fois, il est passé en tant que «mémo» au premier appel de fonction anonyme, puis la valeur renvoyée de la fonction anonyme est transmise en tant qu'argument «mémo» à la fonction suivante.
Un autre exemple du cas d'utilisation classique pour mémo serait de renvoyer le plus petit ou le plus grand nombre d'un tableau. Exemple:
[7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val) // ^this would return the largest number in the list.
Un exemple de la façon d'écrire votre propre fonction de réduction (cela aide souvent à comprendre des fonctions comme celles-ci, je trouve):
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]); // or, more technically complete, give access to base array // and index to the reducer as well: // memo = reduceFunc(memo, this[i], i, this); } // after we've compressed the array into a single value, // we return it. return memo; }
L'implémentation réelle permet d'accéder à des éléments comme l'index, par exemple, mais j'espère que cela vous aidera à avoir une idée simple de l'essentiel.
la source
reduce
est que, contrairement àfilter
+map
, le rappel peut recevoir un argument d'index qui est l'index du tableau d'origine, et non celui de celui filtré.Ce n'est pas ce que fait la carte. Vous voulez vraiment Array.filter . Ou si vous voulez vraiment supprimer les éléments de la liste d'origine, vous allez devoir le faire impérativement avec une boucle for.
la source
Array Filter, méthode
var arr = [1, 2, 3] // ES5 syntax arr = arr.filter(function(item){ return item != 3 }) // ES2015 syntax arr = arr.filter(item => item != 3) console.log( arr )
la source
var arr = [1,2,"xxx", "yyy"]; arr = arr.filter(function(e){ return e!="xxx" }) console.log(arr)
Vous devez cependant noter que le
Array.filter
n'est pas pris en charge dans tous les navigateurs, vous devez donc prototyper://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; }; }
Et ce faisant, vous pouvez prototyper n'importe quelle méthode dont vous pourriez avoir besoin.
la source
L'instruction suivante nettoie l'objet à l'aide de la fonction map.
var arraytoclean = [{v:65, toberemoved:"gronf"}, {v:12, toberemoved:null}, {v:4}]; arraytoclean.map((x,i)=>x.toberemoved=undefined); console.dir(arraytoclean);
la source
Je viens d'écrire une intersection de tableau qui gère correctement également les doublons
https://gist.github.com/gkucmierz/8ee04544fa842411f7553ef66ac2fcf0
// array intersection that correctly handles also duplicates const intersection = (a1, a2) => { const cnt = new Map(); a2.map(el => cnt[el] = el in cnt ? cnt[el] + 1 : 1); return a1.filter(el => el in cnt && 0 < cnt[el]--); }; const l = console.log; l(intersection('1234'.split``, '3456'.split``)); // [ '3', '4' ] l(intersection('12344'.split``, '3456'.split``)); // [ '3', '4' ] l(intersection('1234'.split``, '33456'.split``)); // [ '3', '4' ] l(intersection('12334'.split``, '33456'.split``)); // [ '3', '3', '4' ]
la source
Vous pouvez d'abord utiliser la carte et avec le chaînage, vous pouvez utiliser le filtre
state.map(item => { if(item.id === action.item.id){ return { id : action.item.id, name : item.name, price: item.price, quantity : item.quantity-1 } }else{ return item; } }).filter(item => { if(item.quantity <= 0){ return false; }else{ return true; } });
la source