8
votes

Fusionner des objets JS sans écraser

Supposons que vous ayez deux objets:

var foobar = {
    a : [1, 3],
    b : [2, 4]
}


3 commentaires

Si FOO a une propriété c: 5 mais la barre ne fait pas ... Foobar a-t-il la propriété copiée directement de foo? ou a-t-il c: [5] ?


Êtes-vous intéressé uniquement de propriétés propres ou de propriétés héritées aussi? Et j'ai remarqué que vous l'avez marqué avec jQuery et étendez-vous. Pensez-vous qu'une solution utilise jquery.extend comme base?


Vous devriez être un peu plus spécifique avec ce que vous voulez arriver pour les différents cas que vous demandez de rendre compte. Qu'est-ce que tu veux dire profondément en fusion? La réponse de Robg semble être exactement ce que vous voulez


3 Réponses :


3
votes

Vraisemblablement, vous iriez un objet sur un objet et copieriez ses noms de propriété sur un nouvel objet et des valeurs aux tableaux attribués à ces propriétés. Itéréter sur des objets suivants, ajoutant des propriétés et des tableaux s'ils n'existent pas déjà ou en ajoutant leurs valeurs aux propriétés et aux tableaux existants.

EG P>

function mergeObjects(a, b, c) {
  c = c || {};
  var p;

  for (p in a) {
    if (a.hasOwnProperty(p)) {
      if (c.hasOwnProperty(p)) {
        c[p].push(a[p]);
      } else {
        c[p] = [a[p]];
      }
    }
  }
  for (p in b) {
    if (b.hasOwnProperty(p)) {
      if (c.hasOwnProperty(p)) {
        c[p].push(b[p]);
      } else {
        c[p] = [b[p]];
      }
    }
  }
  return c;
}


6 commentaires

J'ai supposé que c'était évident et non ce que la question demandait


Bien, alors quelle est votre réponse? Il n'y a rien dans l'OP sur la manière de gérer la fusion profonde, peut-être d'autres informations seront révélées en réponse ...


@WALKERNEO - Vraisemblablement, l'OP ne veut pas copier des propriétés héritées ni les ajouter aux propriétés héritées si l'objet (éventuellement) fourni.


@WALKERNEO, HasownProperty S'assure que ce n'est pas une propriété héritée.


Je rétracte ma déclaration alors. Je vais aller chercher ce qu'est une propriété héritée. EDIT: OK, désolé pour ça. J'ai oublié cela.


c [p] .PUSH (A [p]); doit être si (C [p] instance de matrice) {C [p] .Push (A [P]); } else {c [p] = [c [p], un [p]]; }



10
votes

Cela devrait faire ce que vous cherchez. Il fusionnera récursivement des objets arbitrairement profonds dans des matrices.

deepmerge(as, po)
{"a": ["asdf", "poui"], "b": 4, "c": {"q": [1, 444], "w": [function () {return 5;}, function () {return 1123;}]}, "o": {"b": {"t": "cats"}, "q": 7}, "p": 764}
po
{"a": "poui", "c": {"q": 444, "w": function () {return 1123;}}, "o": {"b": {"t": "cats"}, "q": 7}, "p": 764}
as
{"a": "asdf", "b": 4, "c": {"q": 1, "w": function () {return 5;}}}


8 commentaires

Manquer un } après le premier autre, mais en plus de cela, fonctionne bien. Gloire.


ACK! Bonne prise. Désolé pour ça. Je l'ai réparé lorsque je copierais / collé dans JSConsole, mais j'ai oublié de récupérer cela dans mon autre tampon. Merci encore de pointer que sortit - je l'ai réparé :)


Je m'attendrais à une fonction qui fusionne des "objets dans des tableaux" pour avoir une matrice pour chaque propriété, pas un mélange de chaînes, d'objets, de fonctions et ainsi de suite. Il n'entraîne pas non plus les propriétés inhérentes, ni traitez de fonctions possédant de propres propriétés.


Si vous fusionniez deux objets de types complètement différents, vous voudrions peut-être réellement avoir hérité de propriétés dans votre fronge. De plus, je ne vois pas comment traiter des fonctions augmenterait la valeur dans cette solution. On dirait que ce serait une solution plus spécifique de toute façon et je visais une solution générique qui vient de travailler. Si vous vouliez cette fonctionnalité, il ne serait pas difficile de modifier le code ci-dessus pour faire ce que vous vouliez. Je voulais juste répondre à la question et ne pas supposer quoi que ce soit d'autre :)


@Zach - L'OP n'a pas dit quel type d'objets devraient ou ne devraient pas être traités. C'est une bonne idée de signaler des limitations ou des hypothèses afin que l'OP puisse faire une évaluation plus éclairée. En ce qui concerne les propriétés héritées, il ne semble pas que la bonne idée de les copier (mais encore une fois, aucune exigence explicite de toute façon).


Oui, tu as un bon point. Je pourrais le modifier pour inclure une version qui ignore les propriétés héritées. De cette façon si l'OP veut filtrer les propriétés héritées, ils peuvent utiliser cette version.


Il suffit de vous faire savoir que l'ajout de licences pour vos extraits de code est infructueux; En utilisant le site que vous acceptez de la licence de telle (bien que c'est la même licence). Juste un pourboire;)


@Qix merci pour la pointe. C'est honnêtement que je suis assez longuement longtemps que je ne me souviens pas pourquoi j'ai ajouté la licence à l'époque, mais je me souviens de penser que je finirais de courir dans quelqu'un qui l'utilise à un moment donné et que mon commentaire idiot serait toujours là. Évidemment, les gens qui l'utilisent vont probablement simplement supprimer le commentaire (et c'est totalement fin) - mais je pense toujours que je craquerais un sourire si je me suis rentré à nouveau. :)



1
votes

https://lodash.com/docs/3.10.1#merge

p>

    // using a customizer callback
var object = {
  'fruits': ['apple'],
  'vegetables': ['beet']
};

var other = {
  'fruits': ['banana'],
  'vegetables': ['carrot']
};

_.merge(object, other, function(a, b) {
  if (_.isArray(a)) {
    return a.concat(b);
  }
});
// → { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }


1 commentaires

Je sais que cette réponse nécessite que Lodash soit installée, mais je ne vois pas pourquoi cela devait être voté. C'était le seul qui a fonctionné pour moi et était le plus propre!