136 votes

Diviser un tableau par une fonction filtre

J'ai un tableau Javascript que je voudrais diviser en deux en fonction du retour d'une fonction appelée sur chaque élément. true o false . Il s'agit essentiellement d'un array.filter mais j'aimerais également avoir sous la main les éléments qui ont été filtrés. out .

Actuellement, mon plan est d'utiliser array.forEach et appeler la fonction prédicat sur chaque élément. Selon que cette fonction est vraie ou fausse, je vais pousser l'élément actuel sur l'un des deux nouveaux tableaux. Existe-t-il une manière plus élégante ou meilleure de procéder ? Un site array.filter où le poussera l'élément sur un autre tableau avant de retourner false par exemple ?

11voto

codename- Points 1712

Dans la fonction filtre, vous pouvez pousser vos éléments faux dans une autre variable en dehors de la fonction :

var bad = [], good = [1,2,3,4,5];
good = good.filter(function (value) { if (value === false) { bad.push(value) } else { return true});

Bien sûr. value === false il faut que la comparaison soit réelle ;)

Mais il fait presque la même opération que forEach . Je pense que vous devriez utiliser forEach pour une meilleure lisibilité du code.

8voto

Vereb Points 4876

Et ça ?

[1,4,3,5,3,2].reduce( (s, x) => { s[ x > 3 ].push(x); return s;} , {true: [], false:[]} )

Cette méthode est probablement plus efficace que l'opérateur de diffusion.

Ou un peu plus court, mais plus moche

[1,4,3,5,3,2].reduce( (s, x) => s[ x > 3 ].push(x)?s:s , {true: [], false:[]} )

7voto

parktomatomi Points 3083

Beaucoup de réponses ici utilisent Array.prototype.reduce pour construire un accumulateur mutable, et font remarquer à juste titre que pour les grands tableaux, c'est plus efficace que, par exemple, l'utilisation d'un opérateur d'étalement pour copier un nouveau tableau à chaque itération. L'inconvénient est que ce n'est pas aussi joli qu'une expression "pure" utilisant la syntaxe lambda courte.

Mais une façon de contourner ce problème est d'utiliser l'opérateur virgule. Dans les langages de type C, la virgule est un opérateur qui renvoie toujours l'opérande de droite. Vous pouvez l'utiliser pour créer une expression qui appelle une fonction void et renvoie une valeur.

function partition(array, predicate) {
    return array.reduce((acc, item) => predicate(item)
        ? (acc[0].push(item), acc)
        : (acc[1].push(item), acc), [[], []]);
}

Si vous tirez parti du fait qu'une expression booléenne est implicitement convertie en un nombre comme 0 et 1, vous pouvez la rendre encore plus concise, bien que je ne pense pas qu'elle soit aussi lisible :

function partition(array, predicate) {
    return array.reduce((acc, item) => (acc[+!predicate(item)].push(item), acc), [[], []]);
}

Utilisation :

const [trues, falses] = partition(['aardvark', 'cat', 'apple'], i => i.startsWith('a'));
console.log(trues); // ['aardvark', 'apple']
console.log(falses); // ['cat']

6voto

Matsumoto Kazuya Points 109

Facile à lire.

const partition = (arr, condition) => {
    const trues = arr.filter(el => condition(el));
    const falses = arr.filter(el => !condition(el));
    return [trues, falses];
};

// sample usage
const nums = [1,2,3,4,5,6,7]
const [evens, odds] = partition(nums, (el) => el%2 == 0)

5voto

qwertymk Points 9783

Essayez ça :

function filter(a, fun) {
    var ret = { good: [], bad: [] };
    for (var i = 0; i < a.length; i++)
        if (fun(a[i])
            ret.good.push(a[i]);
        else
            ret.bad.push(a[i]);
    return ret;
}

DEMO

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X