1

J'ai donc ce scénario où j'ai un client-app qui envoie des données (tableau d'objets) à un serveur qui transmet ensuite les données à autres clients connecté à ce serveur.tableaux Javascript et objets: Obtenir les différences et les fusionner

Dans le client-app , les données sont en constante évolution, ce qui signifie: Les valeurs changent, de nouveaux objets à l'intérieur du tableau pop-up, les objets étant enlevés, et ainsi de suite ...

Maintenant, je veux le autres clients pour toujours recevoir les dernières données. Et parce que je ne veux pas le client-app juste pousser les toutes nouvelles données au serveur qui transmet ensuite les toutes nouvelles données aux autres clients, j'ai décidé de laisser le client app seulement appuyez sur les changements (en utilisant cette bibliothèque: https://www.npmjs.com/package/deep-object-diff).

Les autres clients reçoivent alors un tableau d'objets avec seulement les données qui ont réellement changé et parce qu'ils savent le tableau de données précédentes, je veux qu'ils « fusionner » le tableau des changements avec l'ancien objet de données .

Mon véritable problème est la fusion. Je ne sais pas comment le faire correctement. Surtout si j'ai un tableau d'objets sans aucune clé pour les objets.

donc mes données ressemble à ceci:

let data = [ 
    { 
    name: 'Peter', 
    age: 26, 
    sID: 546589995544 
    }, 
    { 
    name: 'John', 
    age: 33, 
    sID: 554589525469 
    } 
]; 

En fait, il y a beaucoup plus, mais bien, thats la structure.

Donc, si la bibliothèque diff dit, ce sont les changements:

let changes = { 
    { 
    age: 34, 
    sID: 554589525469 
    } 
}; 

(avis que j'ai maintenant un objet d'objets, et non un tableau d'objets Thats ce que le rendement diff-bibliothèque.)

Je veux l'objet fusionné pour être

[ 
    { 
    name: 'Peter', 
    age: 26, 
    sID: 546589995544 
    }, 
    { 
    name: 'John', 
    age: 34, 
    sID: 554589525469 
    } 
]; 

(John est maintenant un an de plus)

Donc, je crois totalement que ce serait beaucoup plus facile si j'avais une clé pour les objets en tant qu'identifiant, mais je pense toujours qu'il doit y avoir une solution pour exactement ce scénario. Et comme vous pouvez le voir, la propriété sID peut servir d'identifiant, ce n'est juste pas une clé.

J'apprectiate si quelqu'un pouvait indiquer comment le faire dans les deux cas (avec et sans une clé spécifique pour les objets)

+0

Voir https://stackoverflow.com/help/mcve – guest271314

+0

maintenant le code de votre question est invalide ... –

Répondre

1

Vous pouvez utiliser .find() pour trouver l'objet dans le tableau où les valeurs doivent être changées, Object.assign() pour définir les valeurs

let data = [{ 
 
    name: 'Peter', 
 
    age: 26, 
 
    sID: 546589995544 
 
    }, 
 
    { 
 
    name: 'John', 
 
    age: 33, 
 
    sID: 554589525469 
 
    } 
 
]; 
 

 
let changes = [{ 
 
    age: 34, 
 
    sID: 554589525469 
 
}]; 
 

 
for (let prop of changes) { 
 
    let {sID} = prop; 
 
    Object.assign(data.find(({sID: id}) => id === sID), prop) 
 
} 
 

 
console.log(data);

+0

Cela semble être une bonne approche qui fonctionne un peu. Cela ne fonctionne tout simplement pas pour moi car la bibliothèque diff ne renvoie pas un tableau d'objets mais un objet avec des objets en tant que membres. Et puis, vos solutions ne fonctionnent plus, car les modifications [Symbol.iterator] ne sont pas une fonction. Une solution à ce problème? – SVARTBERG

+1

Vous pouvez utiliser 'Object.values ​​()' ou 'Object.entries()' pour convertir un objet en tableau de tableaux de propriétés, paires de valeurs. Pourquoi n'avez-vous pas inclus l'objet utilisé dans le code de Question? – guest271314

+0

Ma faute, sry. N'y ai pas pensé en écrivant la question. Donc vous pensez que je devrais convertir les changements en un tableau d'objets? Je dois regarder comment y parvenir avec vos fonctions suggérées. Merci. – SVARTBERG

1

Vous pouvez utiliser une carte sid pour la recherche rapide:

const byId = new Map(data.map(el => [el.sID, el])); 

Ensuite, pour chaque changement, nous pouvons trouver si l'obj existe déjà, sinon on ajoute, si oui nous muter:

changes.forEach(change => { 
const res = byId.get(change.sID); 
if(res){ 
    Object.assign(res, change); 
}else{ 
    data.push(change); 
    byId.set(change.sID, change); 
} 
}); 
+0

Qu'est-ce que les données dans votre cas? Et genre du même problème que dans le commentaire à la réponse de guest271314 – SVARTBERG

+0

@svartberg ceci est basé sur * votre * code. –

+0

Oh, je suis désolé, n'a pas eu le fait que votre code est en train de remplacer l'ancien objet de données. Merci pour l'instant. Je dois faire d'autres tests – SVARTBERG

1

En utilisant lodash, vous pouvez accomplir cela avec unionBy:

const newData = _.unionBy(changes, data, 'sID'); // values from changes will be picked 

Cela choisir des objets à la fois des tableaux à base sur sID et les combiner en un seul tableau.

+0

Fonctionne jusqu'à ce qu'un nouvel objet soit ajouté aux données initiales. – SVARTBERG

+0

@SVARTBERG lorsqu'un nouvel objet est ajouté, exécutez à nouveau unionBy. – Fawaz

1

Si vos modifications des données est object of objects, vous pouvez utiliser Object.values à la valeur des données de boucle et de fusionner les données mêmes id par Object.assign

let data = [ 
    { 
    name: 'Peter', 
    age: 26, 
    sID: 546589995544 
    }, 
    { 
    name: 'John', 
    age: 33, 
    sID: 554589525469 
    } 
]; 

let changes = { 
    0: 
    { 
    age: 34, 
    sID: 554589525469 
    } 
}; 

data.filter((idx,i)=> 
    Object.values(changes).forEach((index)=> 
     (index.sID == idx.sID) ? Object.assign(data[i],index) : null 
     ) 
); 
console.log(data); 
+0

Merci pour votre réponse. Fonctionne jusqu'ici. Pouvez-vous m'expliquer comment cela fonctionnerait si j'avais et objet d'objets avec des clés pour chaque objet et pas seulement un nouveau champ avec un identifiant unique? – SVARTBERG

+0

Je pense que vous pouvez utiliser 'Object.keys', cela va récupérer les clés d'objet en tant que liste de tableau .. –