Usando Node, estoy implementando un analizador de etiquetas ID3 para obtener el título, el álbum y el artista de los MP3.

Ahora, necesito tomar la información que recibí y agruparla por nombre de álbum.

En mi uso específico, estoy tratando de pasar de

Éste:

[
  { 
    title: 'Break You',
    artist: 'Lamb Of God',
    album: 'Ashes Of The Wake' 
  },
  {
    title: 'An Extra Nail For Your Coffin',
    artist: 'Lamb Of God',
    album: 'Ashes Of The Wake' 
  },
  {
    title: 'Envy And Doubt',
    artist: 'Sever The King',
    album: 'Traitor' 
  },
  {
    title: 'Self Destruct',
    artist: 'Sever The King',
    album: 'Traitor' 
  },
  ...
]

Para esto: (pseudocódigo)

[
  'Ashes Of The Wake'{
    {
      title: 'Break You',
      artist: 'Lamb Of God'
    },
    {
      title: 'An Extra Nail For Your Coffin',
      artist: 'Lamb Of God'
    }  
  }
  'Traitor'{
    {
      title: 'Envy and Doubt',
      artist: 'Sever The King'
    },
    {
      title: 'Self Destruct',
      artist: 'Sever The King'
    }
  },
  ...
]

Cuál sería la mejor forma de hacer esto? Soy relativamente nuevo en JS, por lo que puede ser simple.

2
Kieran E 10 dic. 2015 a las 22:17

4 respuestas

La mejor respuesta

Simplemente use Array.prototype.forEach()

El método forEach() ejecuta una función proporcionada una vez por elemento de matriz.

var data = [{ title: 'Break You', artist: 'Lamb Of God', album: 'Ashes Of The Wake' }, { title: 'An Extra Nail For Your Coffin', artist: 'Lamb Of God', album: 'Ashes Of The Wake' }, { title: 'Envy And Doubt', artist: 'Sever The King', album: 'Traitor' }, { title: 'Self Destruct', artist: 'Sever The King', album: 'Traitor' }],
    grouped = {};

data.forEach(function (a) {
    grouped[a.album] = grouped[a.album] || [];
    grouped[a.album].push({ title: a.title, artist: a.artist });
});
document.write('<pre>' + JSON.stringify(grouped, 0, 4) + '</pre>');
6
Nina Scholz 10 dic. 2015 a las 19:23

Como sugirió Kieran, usar underscore.js le proporciona una solución elegante y fácil.

var groupedData = _.groupBy(data, 'album');

Aquí está el plunker: http://plnkr.co/edit/a7DhxpGx0C4FVMgIjzPY?p=preview

Editar

Me gustaría agregar que le gustaría usar lodash en lugar de subrayar si está trabajando con Node.js

0
Digitrance 10 dic. 2015 a las 19:30

OBS: 'Ashes Of The Wake' y 'Traitor' deben ser matrices, no objetos, porque tienen varios hijos.

No tiene que hacerlo, pero en caso de que quiera usar underscore, como dijo @Daniel, puede usar la función groupBy.

var data = [
  { 
    title: 'Break You',
    artist: 'Lamb Of God',
    album: 'Ashes Of The Wake' 
  },
  {
    title: 'An Extra Nail For Your Coffin',
    artist: 'Lamb Of God',
    album: 'Ashes Of The Wake' 
  },
  {
    title: 'Envy And Doubt',
    artist: 'Sever The King',
    album: 'Traitor' 
  },
  {
    title: 'Self Destruct',
    artist: 'Sever The King',
    album: 'Traitor' 
  }
];
var groupedData = _.groupBy(data, 'album');
console.log(groupedData);

Saldrá:

[
  'Ashes Of The Wake': [
    {
      title: 'Break You',
      artist: 'Lamb Of God'
    },
    {
      title: 'An Extra Nail For Your Coffin',
      artist: 'Lamb Of God'
    }  
  ],
  'Traitor': [
    {
      title: 'Envy and Doubt,
      artist: 'Sever The King'
    },
    {
      title: 'Self Destruct',
      artist: 'Sever The King'
    }
  ]
]

JSFiddle

0
André Pena 10 dic. 2015 a las 19:29

Puede usar Array.prototype.reduce

var output = input.reduce(function(result, value) { 
  result[value.album] = result[value.album] || []; 
  result[value.album].push({ title: value.title, artist: value.artist });
  return result; 
}, {});
2
m1gu3l 10 dic. 2015 a las 19:29