Nous essayons de prendre un tableau qui a ce format:

[
{batchId: 123, files: [{fileName: 'fileA.txt'}, {fileName: 'fileB.txt'}],
{batchId: 456, files: [{fileName: 'fileC.txt'}, {fileName: 'fileD.txt'}],
]

Et l'aplatissez pour qu'il s'exprime comme suit:

[
{batchId: 123, fileName: 'fileA.txt'},
{batchId: 123, fileName: 'fileB.txt'},
{batchId: 456, fileName: 'fileC.txt'},
{batchId: 456, fileName: 'fileD.txt'},
]

Nous espérons qu'il existe un moyen plus élégant de transformer ces données en utilisant une bibliothèque préexistante telle que Ramda ou Lodash, mais toute implémentation javascript serait bien.

1
Gatmando 16 avril 2018 à 18:44

5 réponses

Meilleure réponse

Vous pouvez utiliser les méthodes reduce() et map() et renvoyer un nouveau tableau.

const data = [
{batchId: 123, files: [{fileName: 'fileA.txt'}, {fileName: 'fileB.txt'}]},
{batchId: 456, files: [{fileName: 'fileC.txt'}, {fileName: 'fileD.txt'}]},
]

const result = data.reduce((r, e) => {
  r.push(...e.files.map(o => Object.assign({}, o, {batchId: e.batchId})))
  return r;
}, [])

console.log(result)
2
Nenad Vracar 16 avril 2018 à 15:50

Une autre approche consiste à utiliser R.chain, qui mappe efficacement la fonction fournie sur le liste pour produire une liste de listes, puis aplatit le résultat.

const data =
  [ {batchId: 123, files: [{fileName: 'fileA.txt'}, {fileName: 'fileB.txt'}]}
  , {batchId: 456, files: [{fileName: 'fileC.txt'}, {fileName: 'fileD.txt'}]}
  ]

const fn =
  R.chain(({batchId, files}) => R.map(R.assoc('batchId', batchId), files))

console.log(fn(data))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

À un moment donné dans le futur, vous pourrez probablement utiliser le proposé {{X0} } au lieu de R.chain.

1
Scott Christopher 17 avril 2018 à 11:45

Vous pouvez également utiliser reduce(), le spread operator, map() et Object.assign() vous pouvez obtenir le résultat souhaité.

DEMO

const arr = [{
  batchId: 123,
  files: [{
    fileName: 'fileA.txt'
  }, {
    fileName: 'fileB.txt'
  }]
}, {
  batchId: 456,
  files: [{
    fileName: 'fileC.txt'
  }, {
    fileName: 'fileD.txt'
  }]
}];


let result = arr.reduce((r, o) => {
  return [...r, ...o.files.map(v => {
    return Object.assign(v, {
      batchId: o.batchId
    });
  })];
}, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0
Narendra Jadhav 16 avril 2018 à 16:48

Avec ES6, vous pouvez utiliser des {{X0) }} appelle et aplatit les sous-tableaux résultants par diffusion dans { {X1}}:

const data = [{batchId: 123, files: [{fileName: 'fileA.txt'}, {fileName: 'fileB.txt'}]},{batchId: 456, files: [{fileName: 'fileC.txt'}, {fileName: 'fileD.txt'}]}];

const result = [].concat(...
  data.map(({ batchId, files }) => 
    files.map(({ fileName }) => ({ batchId, fileName })
  )));

console.log(result);
1
Ori Drori 16 avril 2018 à 15:48
var arr = [
    {batchId: 123, files: [{fileName: 'fileA.txt'}, {fileName: 'fileB.txt'}]},
    {batchId: 456, files: [{fileName: 'fileC.txt'}, {fileName: 'fileD.txt'}]},
];

function flatten(array) {
  return array.reduce(function(newArray, item) {
      return newArray.concat(item.files.map(function(file) { 
          return {
             batchId: item.batchId,
             fileName: file.fileName
          };
     }));
  }, []);
}

console.log(flatten(arr));
1
Oscar Paz 16 avril 2018 à 15:53