flatten object inside array

576 views Asked by At

I'm trying to apply the value of the first key:value pair to each value inside the array of the second key:value pair while removing the keys from the books array, resulting in a list that takes this input:

var fictionCatalog = [
  {
    author: 'Michael Crichton',// push into each book
    books: [
      {name: 'Sphere', price: 10.99},
      {name: 'Jurassic Park', price: 5.99},
      {name: 'The Andromeda Strain', price: 9.99},
      {name: 'Prey', price: 5.99}
    ]
  }
]

and log this output:

[
 [ Michael Crichton, 'Sphere', 10.99 ], 
 [ Michael Crichton, 'Jurassic Park', 5.99 ],
 [ Michael Crichton, 'The Andromeda Strain', 9.99 ],
 [ Michael Crichton, 'Prey', 5.99 ]
]

Where I get stuck

var fictionCatalog = [
  {
    author: 'Michael Crichton',
    books: [
      {name: 'Sphere', price: 10.99},
      {name: 'Jurassic Park', price: 5.99},
      {name: 'The Andromeda Strain', price: 9.99},
      {name: 'Prey', price: 5.99}
    ]
  }
]

var collection = fictionCatalog.reduce(function(prev, curr) {
  return prev.concat(curr.author, curr.books);
}, []);

console.log(collection)

4

There are 4 answers

1
thefourtheye On BEST ANSWER

You can map the result of books like this

var collection = fictionCatalog.map(function(obj) {
  return obj.books.map(function(book) {
    return [obj.author, book.name, book.price];
  });
});

console.log(collection);

Output

[ [ [ 'Michael Crichton', 'Sphere', 10.99 ],
    [ 'Michael Crichton', 'Jurassic Park', 5.99 ],
    [ 'Michael Crichton', 'The Andromeda Strain', 9.99 ],
    [ 'Michael Crichton', 'Prey', 5.99 ] ] ]

For each of the items in the fictionCatalog, we apply a function and gather the results in an array. Now, that function actually applies another function to all of its books and returns an array as a result. The second function (applied to all the books), returns the current author, book name and its price.

0
baao On

A combination of map and map will do the trick for you

var fictionCatalog = [
  {
    author: 'Michael Crichton',// push into each book
    books: [
      {name: 'Sphere', price: 10.99},
      {name: 'Jurassic Park', price: 5.99},
      {name: 'The Andromeda Strain', price: 9.99},
      {name: 'Prey', price: 5.99}
    ]
  }
];

var res = fictionCatalog.map(v => {
  return v.books.map(k => {
   return [v.author, k.name, k.price];
  })
});

console.log(res);

0
Jack On

I'd just loop:

var fictionCatalog = [
  {
    author: 'Michael Crichton',
    books: [
      {name: 'Sphere', price: 10.99},
      {name: 'Jurassic Park', price: 5.99},
      {name: 'The Andromeda Strain', price: 9.99},
      {name: 'Prey', price: 5.99}
    ]
  }
]

var collection = [];

for (var a = 0; a < fictionCatalog.length; a++) {
  var author = fictionCatalog[a].author;
  for (var b = 0; b < fictionCatalog[a].books.length; b++) {
     collection.push([
         author,
         fictionCatalog[a].books[b].name,
         fictionCatalog[a].books[b].price
     ]);
  }
}

console.log(collection)

0
Klinger On

How about this:

var fictionCatalog = [
 {
   author: 'Michael Crichton',
   books: [
      {name: 'Sphere', price: 10.99},
      {name: 'Jurassic Park', price: 5.99},
      {name: 'The Andromeda Strain', price: 9.99},
      {name: 'Prey', price: 5.99}
    ]
  }
]

var collection = fictionCatalog.reduce(
  function(prev, curr) {  
    return prev.concat( curr.books.map( 
                               function(book) { 
                                 return [ curr.author, book.name, book.price ]; 
                               }));
}, []);

It uses reduce and map to generate the array with the shape you want.