web-dev-qa-db-fra.com

Fusion de deux collections à l'aide de Underscore.JS

Pourvu que j'ai deux collections:

c1 - [{a:1},{a:2},{a:3}]

et

c2 - [{a:1},{a:7},{a:8}]

quel est le moyen le plus rapide d'ajouter des éléments uniques à partir de c2 en c1 en utilisant Underscore.JS? Les nombres réels dans les collections seraient 2K pour c1 et 500 pour c2, l'opération est effectuée souvent, donc doit être performante!

pdate 1 - J'utilise uniquement Underscore.JS pendant quelques jours, je n'ai pas trouvé de moyen d'ajouter une collection à une autre (je peux filtrer c2 moi-même) - est-ce trivial dans Underscore.JS?

27
user1514042

Ce qui suit:

  • créer un nouveau tableau contenant tous les éléments de c1 et c2. Voir nion .
  • à partir de ce mélange, créez un nouveau tableau qui ne contient que les éléments uniques. Voir niq .

Notez que cela ne fonctionnerait que si tous vos objets ont la propriété a.

_.uniq(_.union(c1, c2), false, function(item, key, a){ return item.a; });

Vous pouvez trouver d'autres options dans cette question .

51
Matias

Essayer:

_.uniq(_.union(c1, c2), false, _.property('a'))

En détail:

  1. _.union(*arrays)

    Calcule l'union des tableaux passés.

  2. _.property(key)(depuis la version 1.6.0)

    Renvoie une fonction qui renverra elle-même la propriété key de tout objet transmis.

  3. _.uniq(array, [isSorted], [iteratee])

    Produit une version sans doublon du tableau, en utilisant === Pour tester l'égalité des objets. Si vous savez à l'avance que le tableau est trié, passer true pour isSorted exécutera un algorithme beaucoup plus rapide. Si vous souhaitez calculer des éléments uniques en fonction d'une transformation, passez une fonction itérative.

15
HaNdTriX

La documentation de la fonction uniq() mentionne qu'elle s'exécute beaucoup plus rapidement si la liste est triée. L'utilisation des appels chaînés peut également améliorer la lisibilité. Vous pouvez donc faire:

_.chain(c1).union(c2).sortBy("a").uniq(true, function(item){ return item.a; }).value();

Ou si vous préférez la version non chaînée (qui est de 11 caractères plus courte mais moins lisible):

_.uniq(_.sortBy(_.union(c1,c2),"a"),true, function(item){ return item.a; });

La documentation et les exemples de uniq() ne précisent pas le fonctionnement de la fonction de rappel. L'algorithme de la fonction uniq() appelle cette fonction sur chaque élément des deux listes. Si le résultat de cette fonction est le même, il supprime cet élément (en supposant qu'il est dupliqué).

union() empêche en fait les doublons quand il est appelé sur un tableau. Nous pouvons également utiliser ce fait:

_.map(_.union(_.pluck(c1,"a"),_.pluck(c2,"a")),function (item) {return {a:item};});

Ce qui précède comme convertit d'abord la liste des objets en tableaux simples (pluck()) puis les combine en utilisant union() et finalement utilise map() pour faire une liste d'objets.

Référence: niq ()

6
AlexStack

Puisqu'il y a un grand nombre de propriétés dans les deux objets et que cet algorithme s'exécute souvent, il serait préférable d'utiliser le noyau Javascript au lieu de n'importe quelle bibliothèque:

//adds all new properties from the src to dst. If the property already exists, updates the number in dst. dst and src are objects
function extendNumberSet( dst, src ) {
    var allVals = [];
    for ( var i = 0; i < dst.length; i++ ) {
        allVals.Push(dst[i].a);
    }
    for ( var i = 0; i < src.length; i++ ) {
        if ( allVals.indexOf( src[i].a ) === -1 ) {
            dst.Push( src[i] );
        }
    }
}

voici n JSfiddle pour le tester .

1
AlexStack