2 votes

Réduire un tableau multidimensionnel d'objets en un seul tableau d'objets

J'ai un tableau multidimensionnel d'objets -

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}]
  }
]

Je dois le convertir en 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 que j'ai actuellement est la suivante

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;
}, []);

Existe-t-il un moyen plus efficace et plus élégant de procéder ? J'essaie d'y parvenir en réduisant le nombre de fois où j'itère sur chaque tableau, en réduisant le code et en améliorant la lisibilité. Comme vous pouvez le voir, les some et find pendant chaque itération augmentent le nombre d'itérations. Y a-t-il un moyen de le réduire ?

5voto

AlexOwl Points 831
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))

1voto

Nina Scholz Points 17120

Vous pouvez prendre un Map pour la collecte d'objets à l'aide de celle-ci id .

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);

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

0voto

procrastinator Points 5270

Voici ce qui me semble lisible (notez que j'ai voté pour clore votre question parce qu'elle est "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]));
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X