2
votes

Comment fusionner les paires clé-valeur de deux tableaux JSON? - Javascript

J'ai deux tableaux JSON comme celui-ci. Je souhaite fusionner leurs paires de valeurs clés. Ce sont des éléments qui sont communs aux deux alors que ce sont des éléments qui ne sont pas communs.

var jsonData1 = [
  {
    firstName: "Sam",
    age: "10"
  },
  {
    firstName: "John",
    age: "11"
  },
  {
    firstName: "Jack",
    age: "12"
  },
  {
    firstName: "Pam",
    age: "13"
  },
  {
    firstName: "Tom",
    age: "14"
  },
  {
    firstName: "Mitch",
    age: "15"
  }
];

var jsonData2 = [
      {
        firstName: "Sam",
        city: "London"
      },
      {
        firstName: "John",
        city: "New York"
      },
      {
        firstName: "Jack",
        city: "Paris"
      },
      {
        firstName: "Pam",
        city: "Moscow"
      },
      {
        firstName: "Roger",
        city: "Shanghai"
      },
      {
        firstName: "Don",
        city: "Jakarta"
      }
    ];

Comme vous pouvez, il y a des firstName dans le 1er tableau qui n'ont pas de ville dans le 2ème tableau. Encore une fois, il y a des firstName dans le 2ème tableau qui n'ont pas de ville dans le 1er tableau.

Je dois regrouper ces 2 tableaux dans un seul tableau, au cas où un firstName n'aurait pas d'âge ou de ville, il sera attribué ' '(chaîne vide).

Le nouveau tableau aura 3 champs, il y a quelques éléments qui auront des valeurs dans 2 champs. Ils ont un champ comme chaîne vide.

Je veux faire cela en utilisant Vanilla JS, je ne veux pas utiliser Jquery, Lodash et Underscore.


1 commentaires

Il n'y a pas de "tableau JSON". Vous avez un littéral de tableau qui contient des littéraux d'objet. Au moment de l'exécution, ce ne sont que des tableaux d'objets, le fait qu'ils aient été déclarés à l'aide de la syntaxe littérale d'objet n'est pas pertinent.


3 Réponses :


3
votes

Il y a plusieurs façons d'aborder cela, mais une option serait de baser cela autour de la méthode Array # reduction () comme suit:

const jsonData1=[{firstName:"Sam",age:"10"},{firstName:"John",age:"11"},{firstName:"Jack",age:"12"},{firstName:"Pam",age:"13"},{firstName:"Tom",age:"14"},{firstName:"Mitch",age:"15"}];
const jsonData2=[{firstName:"Sam",city:"London"},{firstName:"John",city:"New York"},{firstName:"Jack",city:"Paris"},{firstName:"Pam",city:"Moscow"},{firstName:"Roger",city:"Shanghai"},{firstName:"Don",city:"Jakarta"}];


/* 
Use Array#concat() to combine both input arrays before performing
the merge. This will ensure that all items in both arrays are
processed and accounted for during the merge (which is important in
situations where the input arrays differ in length).

Object.values() is used to transform the dictionary resulting from
reduce() to an array
*/
var result = Object.values(
[].concat(jsonData1, jsonData2
).reduce((dict, item) => {

  /* 
  We use Array#reduce is an intermediate step to construct a dictionary
  which maps each unique "item.firstName" to a corresponding object 
  that contains the merged (or yet to be merged) data for this first 
  name
  */
   
  var value = dict[item.firstName] || {}

  /*
  Use Object.assign() to merge existing data for "item.firstName" with
  current item being processed. Also pass default values as first
  argument to ensure all three key values are present in merge result
  */
  value = Object.assign({ firstName : '', age : '', city : ''} , value, item)

  /*
  Update the dictionary with merged data
  */
  dict[item.firstName] = value

  return dict

}, {}))

console.log(result);


6 commentaires

Pouvez-vous me montrer gentiment dans JSFIddle / JSBin? La fonctionnalité d'exécution d'extrait de code ne fonctionne pas


Comme vous pouvez, il y a des prénoms dans le 1er tableau qui n'ont pas de ville dans le 2e tableau. Encore une fois, il y a des firstName dans le 2ème tableau qui n'ont pas de ville dans le 1er tableau. J'ai besoin de regrouper ces 2 tableaux dans un seul tableau, au cas où un prénom n'a pas d'âge ou de ville, il sera attribué '' (chaîne vide). Le nouveau tableau aura 3 champs, il y a quelques éléments qui auront des valeurs dans 2 champs. Ils ont un champ comme chaîne vide


Il y aura 3 champs pour tout, votre solution a 2 champs pour certains articles


Il devrait y avoir 3 champs pour tous, au cas où un champ / clé n'est pas présent, je dois attribuer '' (chaîne vide)


l'âge doit également avoir la chaîne '', pas zéro


J'ai voté pour votre réponse et l'ai marquée comme correcte. L'autre personne m'a répondu plus tôt, mais je vous ai voté pour parce que votre réponse contient beaucoup de commentaires et aide à comprendre.



0
votes

Une approche possible:

const jsonData1=[{firstName:"Sam",age:"10"},{firstName:"John",age:"11"},{firstName:"Jack",age:"12"},{firstName:"Pam",age:"13"},{firstName:"Tom",age:"14"},{firstName:"Mitch",age:"15"}];
const jsonData2=[{firstName:"Sam",city:"London"},{firstName:"John",city:"New York"},{firstName:"Jack",city:"Paris"},{firstName:"Pam",city:"Moscow"},{firstName:"Roger",city:"Shanghai"},{firstName:"Don",city:"Jakarta"}];

const result = [].concat(jsonData1, jsonData2).reduce((acc, ele) => {
        const existing = acc.find(x => x.firstName === ele.firstName);
        if(!existing) return acc.concat({firstName: ele.firstName, city: ele.city || '', age: ele.age || ''});
        Object.keys(ele).forEach(x => existing[x] = ele[x]);
        return acc;
    },[])
    
console.log(result);


3 commentaires

Comme vous pouvez, il y a des prénoms dans le 1er tableau qui n'ont pas de ville dans le 2e tableau. Encore une fois, il y a des firstName dans le 2ème tableau qui n'ont pas de ville dans le 1er tableau. J'ai besoin de regrouper ces 2 tableaux dans un seul tableau, au cas où un prénom n'a pas d'âge ou de ville, il sera attribué '' (chaîne vide). Le nouveau tableau aura 3 champs, il y a quelques éléments qui auront des valeurs dans 2 champs. Ils ont un seul champ comme chaîne vide.


Il y aura 3 champs pour tout, votre solution a 2 champs pour certains articles


@ tommy123 mis à jour en ajoutant des chaînes vides La clé de lactosérum n'est pas définie =)



0
votes

Je me rends compte que vous avez déjà accepté une réponse, mais je me suis dit que je pourrais vous proposer une alternative, meilleure ou pire.

var jsonData1 = [{firstName: "Sam",age: "10"},{firstName: "John",age: "11"},{firstName: "Jack",age: "12"},{firstName: "Pam",age: "13"},{firstName: "Tom",age: "14"},{firstName: "Mitch",age: "15"}];
var jsonData2 = [{firstName: "Sam",city: "London"},{firstName: "John",city: "New York"},{firstName: "Jack",city: "Paris"},{firstName: "Pam",city: "Moscow"},{firstName: "Roger",city: "Shanghai"},{firstName: "Don",city: "Jakarta"}];

var defaults = {firstName: "", age: "", city: ""};
var data  = [ ...jsonData1, ...jsonData2 ];
var names = [ ...new Set(data.map(i=>i.firstName)) ];

var res = names.map(n => data
                  .reduce((acc, jd) => jd.firstName === n ? {...acc, ...jd} : acc, defaults)
                );

console.log(res);

var data combine les deux tableaux de données en un seul en utilisant syntaxe de propagation (littéraux de tableau) .

noms de var crée un tableau de noms uniques utilisant Set .

map () parcourt la liste des noms, créant un seul objet fusionné pour chacun. Cette fusion est effectuée à l'aide de réduire ( ) et syntaxe de propagation (littéraux d'objet) .


0 commentaires