2
votes

Réduisez le tableau multidimensionnel d'objets en un seul tableau d'objets

J'ai ce tableau multidimensionnel d'objets -

initialArray.reduce((accum, arrayData) => {
  arrayData.value.forEach(element => {
    if (accum.some(el => el.id === element.id)) {
      accum.find(el => el.id === element.id)[arrayData.name] = element.data;
    } else {
        accum.push({ id: element.id, [arrayData.name]: element.data });
    }
  });
  return accum;
}, []);

Je dois le convertir dans ce tableau -

const finalArray = [
  {
    id: 1, aaa: 1, bbb: 4, ccc: 7, ddd: 2
  },
  {
    id: 2, aaa: 2, bbb: 5, ccc: 8, ddd: 1
  },
  {
    id: 3, aaa: 3, bbb: 6, ccc: 7, ddd: 1
  }
]

La solution I ont en ce moment

const initialArray = [
  {
   name: 'aaa', 
   value:[{id:1, data:1}, {id:2, data:2}, {id:3, data:3}]
  },
  {
   name: 'bbb', 
   value:[{id:1, data:4}, {id:2, data:5}, {id:3, data:6}]
  },
  {
   name: 'ccc', 
   value:[{id:1, data:7}, {id:2, data:8}, {id:3, data:7}]
  },
  {
   name: 'ddd', 
   value:[{id:1, data:2}, {id:2, data:1}, {id:3, data:1}]
  }
]

Y a-t-il une manière meilleure et plus élégante de faire cela? J'essaie d'accomplir cela en réduisant le nombre de fois que j'itère dans chaque tableau et avec moins de code et plus de lisibilité. Comme vous pouvez le voir, le some and find lors de chaque itération augmente le nombre d'itérations. Y a-t-il un moyen de le réduire?


1 commentaires

J'ai une réponse à votre question supprimée. Si vous pouvez poster à nouveau votre question, je peux vous donner une solution.


3 Réponses :


5
votes

function tranform(array) {
  const obj = {}
  
  array.forEach(({name, value}) => (value || []).forEach(({id, data}) => obj[id] = { id, ...obj[id], [name]: data } ))
  
  return Object.values(obj)
}

const initialArray = [
  {
   name: 'aaa', 
   value:[{id:1, data:1}, {id:2, data:2}, {id:3, data:3}]
  },
  {
   name: 'bbb', 
   value:[{id:1, data:4}, {id:2, data:5}, {id:3, data:6}]
  },
  {
   name: 'ccc', 
   value:[{id:1, data:7}, {id:2, data:8}, {id:3, data:7}]
  },
  {
   name: 'ddd', 
   value:[{id:1, data:2}, {id:2, data:1}, {id:3, data:1}]
  }
]

console.log(tranform(initialArray))


0 commentaires

1
votes

Vous pouvez prendre une Map pour collecter des objets avec le même id.

.as-console-wrapper { max-height: 100% !important; top: 0; }
var initialArray = [{ name: 'aaa', value: [{ id: 1, data: 1 }, { id: 2, data: 2 }, { id: 3, data: 3 }] }, { name: 'bbb', value: [{ id: 1, data: 4 }, { id: 2, data: 5 }, { id: 3, data: 6 }] }, { name: 'ccc', value: [{ id: 1, data: 7 }, { id: 2, data: 8 }, { id: 3, data: 7 }] }, { name: 'ddd', value: [{ id: 1, data: 2 }, { id: 2, data: 1 }, { id: 3, data: 1 }] }],
    result = Array.from(initialArray
        .reduce(
            (m, { name, value }) => value.reduce(
                (n, { id, data }) => n.set(id, Object.assign(
                    n.get(id) || { id },
                    { [name]: data }
                )),
                m
            ),
            new Map
        )
        .values()
    );

console.log(result);


2 commentaires

semble compliquer un peu les choses. La réponse d'Alex fonctionne mieux.


La réponse de @ajyvardan Alex ne fonctionne pas mieux, les deux réponses donnent le résultat attendu. Vous pouvez penser que la réponse d'Alex est plus lisible mais ce n'est que votre opinion. Comme beaucoup de gens, vous pensez que la lisibilité est l'aspect le plus important de la programmation, mais c'est une façon de penser naïve. Vous devriez mieux considérer les performances ...



0
votes

Voici ce qui me semble lisible (notez que j'ai voté pour fermer votre question parce que "principalement basée sur l'opinion"):

initial = [{ 
  name : "aaa",
  value : [
    { id : 1, data : 1 },
    { id : 2, data : 2 },
    { id : 3, data : 3 }
  ]
}, {
  name : "bbb",
  value : [
    { id : 1, data : 4 },
    { id : 2, data : 5 },
    { id : 3, data : 6 }
  ]
}, {
  name : "ccc",
  value : [
    { id : 1, data : 7 },
    { id : 2, data : 8 },
    { id : 3, data : 7 }
  ]
}, {
  name : "ddd",
  value : [
    { id : 1, data : 2 },
    { id : 2, data : 1 },
    { id : 3, data : 1 }
  ]
}];

map = {};
final = [];

for (i = 0; i < initial.length; i++) {
  x = initial[i];
  for (j = 0; j < x.value.length; j++) {
    y = x.value[j];
    if (!map[y.id]) map[y.id] = { id: y.id };
    map[y.id][x.name] = y.data;
  }
}

for (k in map) {
  final.push(map[k]);
}

for (i = 0; i < final.length; i++) {
  console.log(JSON.stringify(final[i]));
}


0 commentaires