Comment filtrer un tableau de tous les éléments d’un autre tableau

J’aimerais comprendre le meilleur moyen de filtrer un tableau de tous les éléments d’un autre . J’ai essayé avec la fonction de filtrage, mais je ne sais pas comment lui donner les valeurs que je veux supprimer.
Quelque chose comme:

var array = [1,2,3,4]; var anotherOne = [2,4]; var filteredArray = array.filter(myCallback); // filteredArray should now be [1,3] function myCallBack(){ return element ! filteredArray; //which clearly can't work since we don't have the reference <,< } 

Si la fonction de filtrage n’est pas utile, comment l’implémenteriez-vous?
Edit: j’ai vérifié la question possible en double, et cela pourrait être utile pour ceux qui comprennent facilement le javascript. La réponse vérifiée comme bonne rend les choses faciles.

Vous pouvez utiliser le paramètre this de la fonction filter () pour éviter de stocker votre tableau de filtres dans une variable globale.

 var filtered = [1, 2, 3, 4].filter( function(e) { return this.indexOf(e) < 0; }, [2, 4] ); 

Je ferais comme suit:

 var arr = [1,2,3,4], brr = [2,4], res = arr.filter(f => !brr.includes(f)); console.log(res); 
 var array = [1,2,3,4]; var anotherOne = [2,4]; var filteredArray = array.filter(myCallBack); function myCallBack(el){ return anotherOne.indexOf(el) < 0; } 

Dans le rappel, vous vérifiez si chaque valeur du array est dans une anotherOne

https://jsfiddle.net/0tsyc1sx/

Si vous utilisez lodash.js , utilisez _.difference

 filteredArray = _.difference(array, anotherOne); 

Démo

Si vous avez un tableau d'objects:

 var array = [{id :1, name :"test1"},{id :2, name :"test2"},{id :3, name :"test3"},{id :4, name :"test4"}]; var anotherOne = [{id :2, name :"test2"}, {id :4, name :"test4"}]; var filteredArray = array.filter(function(array_el){ return anotherOne.filter(function(anotherOne_el){ return anotherOne_el.id == array_el.id; }).length == 0 }); 

Tableau de démonstration des objects

Démo diff tableau d'objects avec lodash

  /* Here's an example that uses (some) ES6 Javascript semantics to filter an object array by another object array. */ // x = full dataset // y = filter dataset let x = [ {"val": 1, "text": "a"}, {"val": 2, "text": "b"}, {"val": 3, "text": "c"}, {"val": 4, "text": "d"}, {"val": 5, "text": "e"} ], y = [ {"val": 1, "text": "a"}, {"val": 4, "text": "d"} ]; // Use map to get a simple array of "val" values. Ex: [1,4] let yFilter = y.map(itemY => { return itemY.val; }); // Use filter and "not" includes to filter the full dataset by the filter dataset's val. let filteredX = x.filter(itemX => !yFilter.includes(itemX.val)); // Print the result. console.log(filteredX); 

La meilleure description de la fonction de filter est https://developer.mozilla.org/pl/docs/Web/JavaScript/Referencje/Obiekty/Array/filter

Vous devez simplement conditionner la fonction:

 function conditionFun(element, index, array) { return element >= 10; } filtered = [12, 5, 8, 130, 44].filter(conditionFun); 

Et vous ne pouvez pas accéder à la valeur de la variable avant qu’elle soit affectée

Vous pouvez utiliser le filtre, puis, pour la fonction de filtrage, utiliser une réduction du tableau de filtrage qui vérifie et renvoie true lorsqu’il trouve une correspondance, puis inverse lors du retour (!). La fonction de filtrage est appelée une fois par élément du tableau. Vous ne comparez aucun des éléments de la fonction dans votre message.

 var a1 = [1, 2, 3, 4], a2 = [2, 3]; var filtered = a1.filter(function(x) { return !a2.reduce(function(y, z) { return x == y || x == z || y == true; }) }); document.write(filtered); 

Un tableau de filtrage plus flexible d’un autre tableau contenant des propriétés d’object

 function filterFn(array, diffArray, prop, propDiff) { diffArray = !propDiff ? diffArray : diffArray.map(d => d[propDiff]) this.fn = f => diffArray.indexOf(f) === -1 if (prop) { return array.map(r => r[prop]).filter(this.fn) } else { return array.filter(this.fn) } } //You can use it like this; var arr = []; for (var i = 0; i < 10; i++) { var obj = {} obj.index = i obj.value = Math.pow(2, i) arr.push(obj) } var arr2 = [1, 2, 3, 4, 5] var sec = [{t:2}, {t:99}, {t:256}, {t:4096}] var log = console.log.bind(console) var filtered = filterFn(arr, sec, 'value', 't') var filtered2 = filterFn(arr2, sec, null, 't') log(filtered, filtered2) 

Les exemples suivants utilisent new Set() pour créer un tableau filtré contenant uniquement des éléments uniques:

Tableau avec types de données primitifs: chaîne, nombre, booléen, null, non défini, symbole:

 const a = [1, 2, 3, 4]; const b = [3, 4, 5]; const c = Array.from(new Set(a.concat(b))); 

Tableau contenant des objects en tant qu’éléments:

 const a = [{id:1}, {id: 2}, {id: 3}, {id: 4}]; const b = [{id: 3}, {id: 4}, {id: 5}]; const ssortingngifyObject = o => JSON.ssortingngify(o); const parseSsortingng = s => JSON.parse(s); const c = Array.from(new Set(a.concat(b).map(ssortingngifyObject)), parseSsortingng); 

Toutes les solutions ci-dessus “fonctionnent”, mais ne sont pas optimales pour les performances et sont toutes proches du problème de la même manière qui recherche linéairement toutes les entrées à chaque point en utilisant Array.prototype.indexOf ou Array.prototype.includes . Une solution beaucoup plus rapide (beaucoup plus rapide que la recherche binary dans la plupart des cas) consisterait à sortinger les tableaux et à passer à la suite, comme indiqué ci-dessous. Cependant, un inconvénient est que toutes les entrées du tableau doivent être des nombres ou des chaînes. Cependant, dans certains cas rares, la recherche binary peut être plus rapide que la recherche linéaire progressive. Ces cas résultent du fait que ma recherche linéaire progressive a une complexité de O (2n 1 + n 2 ) (seulement O (n 1 + n 2 ) dans la version C / C ++ plus rapide) (où n 1 est le tableau recherché et n 2 est le tableau de filtres), alors que la recherche binary a une complexité de O (n 1 ceil (log 2 n 2 )) (ceil = arrondi – au plafond ) et, enfin, la recherche indexOf a un complexité très variable entre O (n 1 ) et O (n 1 n 2 ) , en moyenne sur O (n 1 ceil (n 2 ÷ 2)) . Ainsi, indexOf ne sera que le plus rapide, en moyenne, dans les cas de (n 1 , n 2 ) égalant {1,2} , {1,3} ou {x, 1 | x∈N} . Cependant, ce n’est toujours pas une représentation parfaite du matériel moderne. IndexOf est nativement optimisé dans toute la mesure du possible dans la plupart des navigateurs modernes, ce qui le rend très sensible aux lois de la prédiction de twig . Ainsi, si nous faisons la même hypothèse sur indexOf que nous le faisons avec la recherche linéaire et binary progressive – à savoir que le tableau est sortingé – alors, selon les statistiques listées dans le lien, nous pouvons nous attendre à une accélération d’environ 6x pour IndexOf, déplacer sa complexité entre O (n 1 ÷ 6) et O (n 1 n 2 ) , en faisant la moyenne sur O (n 1 ceil (n 2 7 ÷ 12)) . Enfin, notez que la solution ci-dessous ne fonctionnera jamais avec des objects car il est impossible d’obtenir le pointeur d’object interne (pour la comparaison numérique) en javascript.

 function sortAnyArray(a,b) { return a>b ? 1 : (a===b ? 0 : -1); } function sortIntArray(a,b) { return a - b; } var Math_clz32 = Math.clz32; function filterArrayByAnotherArray(searchArray, filterArray, isInteger = false, i = 0) { if (isInteger) { // if all ensortinges in both arrays are integers searchArray.sort(sortIntArray); filterArray.sort(sortIntArray); } else { searchArray.sort(sortAnyArray); filterArray.sort(sortAnyArray); } var searchArrayLen = searchArray.length, filterArrayLen = filterArray.length; var progressiveLinearComplexity = ((searchArrayLen< <1) + filterArrayLen)>>>0 var binarySearchComplexity= (searchArrayLen * (32-Math_clz32(filterArrayLen-1)))>>>0; // After computing the complexity, we can predict which algorithm will be the fastest if (progressiveLinearComplexity < binarySearchComplexity) { // Progressive Linear Search return searchArray.filter(function(currentValue){ while (filterArray[i] < currentValue) ++i; // +undefined = NaN, which is always false for <, avoiding an infinite loop return filterArray[i] !== currentValue; }); } else { // Binary Search return searchArray.filter(function(currentValue) { var lo = -1, hi = filterArrayLen; while (1 + lo !== hi) { const mi = (hi + lo) >> 1; if (currentValue < = filterArray[mi]) hi = mi; else lo = mi; } return filterArray[hi] !== currentValue; }); } } 

Pour prouver la différence de vitesse, examinons quelques JSPerfs. Pour filtrer un tableau de 16 éléments , la recherche binary est environ 17% plus rapide que indexOf alors que filterArrayByAnotherArray est environ 93% plus rapide que indexOf. Pour filtrer un tableau de 256 éléments , la recherche binary est environ 291% plus rapide que indexOf alors que filterArrayByAnotherArray est environ 353% plus rapide que indexOf. Pour filtrer un tableau de 4096 éléments , la recherche binary est environ 2655% plus rapide que indexOf alors que filterArrayByAnotherArray est environ 4627% plus rapide que indexOf.

Vous pouvez configurer la fonction de filtrage pour parcourir le “tableau de filtres”.

 var arr = [1, 2, 3 ,4 ,5, 6, 7]; var filter = [4, 5, 6]; var filtered = arr.filter( function(val) { for (var i = 0; i < filter.length; i++) { if (val == filter[i]) { return false; } } return true; } ); 
 var arr1= [1,2,3,4]; var arr2=[2,4] function fil(value){ return value !=arr2[0] && value != arr2[1] } document.getElementById("p").innerHTML= arr1.filter(fil) 
 < !DOCTYPE html>     

 function arr(arr1,arr2){ function filt(value){ return arr2.indexOf(value) === -1; } return arr1.filter(filt) } document.getElementById("p").innerHTML = arr([1,2,3,4],[2,4]) 
 

Vous pouvez écrire une fonction filterByIndex () générique et utiliser l’inférence de type dans TS pour enregistrer les problèmes avec la fonction de rappel:

Disons que vous avez votre tableau [1,2,3,4] que vous voulez filtrer () avec les index spécifiés dans le tableau [2,4].

 var filtered = [1,2,3,4,].filter(byIndex(element => element, [2,4])) 

la fonction byIndex attend la fonction element et un tableau et ressemble à ceci:

 byIndex = (getter: (e:number) => number, arr: number[]) => (x: number) => { var i = getter(x); return arr.indexOf(i); } 

le résultat est alors

 filtered = [1,3] 

L’OA peut également être implémenté dans ES6 comme suit

ES6:

  const filtered = [1, 2, 3, 4].filter(e => { return this.indexOf(e) < 0; },[2, 4]);