2017-08-16 8 views
-2

J'ai deux ensembles d'objets JavaScript. Je veux comparer object1 à object2, puis obtenir une liste de toutes les clés qui sont dans object1, mais pas dans object2. J'ai cherché des ressources pour m'aider, mais j'ai fini par trouver des fonctions de comparaison pour des objets simples. Les objets que je veux comparer ont beaucoup d'imbrication. J'ai inclus un exemple en bas.Comparaison des clés de deux objets JavaScript

Comment est-ce que je ferais une fonction pour comparer ces deux objets? Est-il possible de créer une fonction flexible, qui fonctionnerait également si les objets devaient changer et contenir plus d'imbrication?

const object1 = { 
    "gender": "man", 
    "age": 33, 
    "origin": "USA", 
    "jobinfo": { 
     "type": "teacher", 
     "school": "Wisconsin" 
    }, 
    "children": [ 
     { 
      "name": "Daniel", 
      "age": 12, 
      "pets": [ 
       { 
        "type": "cat", 
        "name": "Willy", 
        "age": 2 
       }, 
       { 
        "type": "dog", 
        "name": "jimmie", 
        "age": 5 
       } 
      ] 
     }, 
     { 
      "name": "Martin", 
      "age": 14, 
      "pets": [ 
       { 
        "type": "bird", 
        "name": "wagner", 
        "age": 12 
       } 
      ] 
     } 
    ], 
    "hobbies": { 
     "type": "football", 
     "sponsor": { 
      "name": "Pepsi", 
      "sponsorAmount": 1000, 
      "contact": { 
       "name": "Leon", 
       "age": 59, 
       "children": [ 
        { 
         "name": "James", 
         "pets": [ 
          { 
           "type": "dog", 
           "age": 4 
          } 
         ] 
        } 
       ] 
      } 
     } 
    } 
} 

const object2 = { 
    "gender": "man", 
    "jobinfo": { 
     "type": "teacher" 
    }, 
    "children": [ 
     { 
      "name": "Daniel", 
      "age": 12, 
      "pets": [ 
       { 
        "type": "cat", 
        "name": "Willy", 
        "age": 2 
       }, 
       { 
        "type": "dog", 
        "name": "jimmie", 
        "age": 5 
       } 
      ] 
     } 
    ] 
} 

donc ce que je veux réaliser en comparant ces deux objets, est dans ce cas d'avoir un rendement de tableau qui se compose des clés qui sont object1, mais pas object2. Ainsi, le tableau ressemblerait à ceci.

["age", "hobbies", "type", "sponsor", "name", "sponsorAmount", "contact", "name", "age", "children", "name", "pets", "type", "age"]. 

C'est ce que j'ai obtenu jusqu'à présent. C'est en quelque sorte de travailler. Mais il ne s'agit pas d'imprimer l'âge par exemple, car l'âge est une propriété qui existe dans plusieurs des objets imbriqués. jsFiddle: https://jsfiddle.net/rqdgojq2/

J'ai eu un regard sur les ressources suivantes:

+0

s'il vous plaît ajouter le résultat souhaité et ce que vous avez essayé. peut-être un coup d'oeil vaut: [mcve]. –

+0

Désolé, j'ai mis à jour le poste maintenant avec plus d'informations. Merci pour les commentaires. –

+0

avez-vous besoin également des indices des tableaux? Avez-vous besoin du résultat dans l'ordre d'itération? –

Répondre

0

Merci pour les commentaires. J'ai fini par le résoudre, avec beaucoup d'inspiration de la part de Romans.

const compareObjects = (obj1, obj2) => { 
    function getAllKeyNames(o, arr, str){ 
     Object.keys(o).forEach(function(k){ 
      if (Object.prototype.toString.call(o[k]) === "[object Object]") { 
       getAllKeyNames(o[k], arr, (str + '.' + k)); 
      } else if (Array.isArray(o[k])) { 
       o[k].forEach(function(v){ 
        getAllKeyNames(v, arr, (str + '.' + k)); 
       }); 
      } 
      arr.push(str + '.' + k); 
     }); 
    } 

    function diff(arr1, arr2) { 
     for(let i = 0; i < arr2.length; i++) { 
      arr1.splice(arr1.indexOf(arr2[i]), 1); 
     } 
     return arr1; 
    } 

    const o1Keys = []; 
    const o2Keys = []; 
    getAllKeyNames(obj1, o1Keys, ''); // get the keys from schema 
    getAllKeyNames(obj2, o2Keys, ''); // get the keys from uploaded file 

    const missingProps = diff(o1Keys, o2Keys); // calculate differences 
    for(let i = 0; i < missingProps.length; i++) { 
     missingProps[i] = missingProps[i].replace('.', ''); 
    } 
    return missingProps; 
} 

jsFiddle ici: https://jsfiddle.net/p9Lm8b53/

1

solution complexe à l'aide Set objet et personnalisée getAllKeyNames() fonction récursive obtenir tous les noms de clés uniques à partir de l'objet spécifié:

var object1 = {"gender":"man","age":33,"origin":"USA","jobinfo":{"type":"teacher","school":"Wisconsin"},"children":[{"name":"Daniel","age":12,"pets":[{"type":"cat","name":"Willy","age":2},{"type":"dog","name":"jimmie","age":5}]},{"name":"Martin","age":14,"pets":[{"type":"bird","name":"wagner","age":12}]}],"hobbies":{"type":"football","sponsor":{"name":"Pepsi","sponsorAmount":1000,"contact":{"name":"Leon","age":59,"children":[{"name":"James","pets":[{"type":"dog","age":4}]}]}}}}, 
 
    object2 = {"gender":"man","age":33,"origin":"USA","jobinfo":{"type":"teacher","school":"Wisconsin"},"children":[{"name":"Daniel","age":12,"pets":[{"type":"cat","name":"Willy","age":2},{"type":"dog","name":"jimmie","age":5}]}]}; 
 
    
 
    function getAllKeyNames(o, res){ 
 
     Object.keys(o).forEach(function(k){ 
 
      if (Object.prototype.toString.call(o[k]) === "[object Object]") { 
 
       getAllKeyNames(o[k], res); 
 
      } else if (Array.isArray(o[k])) { 
 
       o[k].forEach(function(v){ 
 
        getAllKeyNames(v, res); 
 
       }); 
 
      } 
 
      res.add(k); 
 
     }); 
 
    } 
 
    
 
    var o1Keys = new Set(), o2Keys = new Set(); 
 
    getAllKeyNames(object1, o1Keys); // unique keys of object1 
 
    getAllKeyNames(object2, o2Keys); // unique keys of object2 
 
    
 
    // get a list of all the keys that are in object1, but not in object2 
 
    var diff = [...o1Keys].filter((x) => !o2Keys.has(x)); 
 
    console.log(diff); 
 

+0

Il semble très propre, mais j'ai besoin d'obtenir toutes les clés d'un objet, et de les comparer. Donc si un objet a deux clés avec le nom "age", et l'autre objet n'a qu'une seule clé avec le nom "age", il ajoutera la clé "age" au tableau. Dans ce jsfiddle, j'ai enlevé le "age" de object2, mais il n'est pas ajouté au tableau. https://jsfiddle.net/4ze7ksx6/2/ –

0

Vous pouvez utiliser un objet pour le comptage.

function getCount(object, keys, inc) { 
 
    Object.keys(object).forEach(function (k) { 
 
     if (!Array.isArray(object)) { 
 
      keys[k] = (keys[k] || 0) + inc; 
 
      if (!keys[k]) { 
 
       delete keys[k]; 
 
      } 
 
     } 
 
     if (object[k] && typeof object[k] === 'object') { 
 
      getCount(object[k], keys, inc) 
 
     } 
 
    }); 
 
} 
 

 
var object1 = { gender: "man", age: 33, origin: "USA", jobinfo: { type: "teacher", school: "Wisconsin" }, children: [{ name: "Daniel", age: 12, pets: [{ type: "cat", name: "Willy", age: 2 }, { type: "dog", name: "jimmie", age: 5 }] }, { name: "Martin", age: 14, pets: [{ type: "bird", name: "wagner", age: 12 }] }], hobbies: { type: "football", sponsor: { name: "Pepsi", sponsorAmount: 1000, contact: { name: "Leon", age: 59, children: [{ name: "James", pets: [{ type: "dog", age: 4 }] }] } } } }, 
 
    object2 = { gender: "man", jobinfo: { type: "teacher" }, children: [{ name: "Daniel", age: 12, pets: [{ type: "cat", name: "Willy", age: 2 }, { type: "dog", name: "jimmie", age: 5 }] }] }, 
 
    count = {}; 
 

 
getCount(object1, count, 1); 
 
getCount(object2, count, -1); 
 

 
console.log(count);
.as-console-wrapper { max-height: 100% !important; top: 0; }