Después de días de tirarme del pelo, decidí buscar ayuda:
Tengo una variedad de objetos, uno para cada artículo de la tienda de comestibles. Cada objeto tiene 3 propiedades: categoría (cadena para la categoría del artículo), itemName (cadena para el artículo en sí) y onSale (booleano, ya sea que esté en oferta o no):
var itemData = [ { category: 'fruit', itemName: 'apple', onSale: false }, { category: 'canned', itemName: 'beans', onSale: false }, { category: 'canned', itemName: 'corn', onSale: true }, { category: 'frozen', itemName: 'pizza', onSale: false }, { category: 'fruit', itemName: 'melon', onSale: true }, { category: 'canned', itemName: 'soup', onSale: false }, ];Necesito convertirlo en un objeto cuyas propiedades son las categorías de objetos. Cada propiedad es una matriz que contiene valores en itemName que corresponden a la propiedad:
{ fruit: ['apple', 'melon($)'], canned: ['beans', 'corn($)', 'soup'], frozen: ['pizza'] };Cuando trato de hacerlo, termino con valores direccionalmente correctos, excepto que se repiten:
{ fruit: [ 'apple', 'apple', 'melon', 'melon', 'melon' ], canned: [ 'beans', 'beans', 'corn', 'corn', 'corn', 'soup', 'soup', 'soup' ], frozen: [ 'pizza', 'pizza' ] }Pasé horas tratando de averiguar dónde me equivoqué, sin éxito. Aquí está mi código:
function organizeItems (array){ //create output obj var output = {} //iterate over the array for(var i = 0; i < array.length; i++){ //iterate over the object in the array for(var category in array[i]){ //if value of category isn't in output add the value to output as an empty array if(output[array[i]["category"]] === undefined){ output[array[i]["category"]] = []; //if not --> push the itemName to the category } else{ output[array[i]["category"]].push(array[i]["itemName"]) } } } return output }¿Cómo puedo evitar la repetición y terminar con los valores correctos en las matrices?
Utilizar Array.prototype.reduce
{} ... que dentro de la función reductora se denomina result . Este último, al iterar la matriz, se compila/acumula mediante programación con cada nueva category y/o itemName . Desestructurar (cada uno) el item de matriz de itemData .
(Crear y/o) Acceder a la matriz específica de la category mediante la asignación lógica nula... ??=
push la forma correcta (dependiendo del estado onSale ) de un artículo de categoría; por ejemplo, utilizando un literal de Plantilla
var itemData = [ { category: 'fruit', itemName: 'apple', onSale: false }, { category: 'canned', itemName: 'beans', onSale: false }, { category: 'canned', itemName: 'corn', onSale: true }, { category: 'frozen', itemName: 'pizza', onSale: false }, { category: 'fruit', itemName: 'melon', onSale: true }, { category: 'canned', itemName: 'soup', onSale: false }, ]; // // expected result ... // { // fruit: ['apple', 'melon($)'], // canned: ['beans', 'corn($)', 'soup'], // frozen: ['pizza'] // }; console.log( itemData.reduce((result, item) => { // destructure `itemData`'s array `item`. const { category, itemName, onSale } = item; // (create and/or) access the `category` specific array. const categoryArray = (result[category] ??= []); // push the correct (depending on `onSale` state) form of a category item. categoryArray.push(`${ itemName }${ (onSale === true) ? '($)' : '' }`); return result; }, {}) ); .as-console-wrapper { min-height: 100%!important; top: 0; }Puede agrupar por category y ajustar itemName .
const itemData = [{ category: 'fruit', itemName: 'apple', onSale: false }, { category: 'canned', itemName: 'beans', onSale: false }, { category: 'canned', itemName: 'corn', onSale: true }, { category: 'frozen', itemName: 'pizza', onSale: false }, { category: 'fruit', itemName: 'melon', onSale: true }, { category: 'canned', itemName: 'soup', onSale: false }], result = itemData.reduce((r, { category, itemName, onSale }) => { itemName += onSale ? ' ($)' : ''; (r[category] ??= []).push(itemName); return r; }, {}); console.log(result); .as-console-wrapper { max-height: 100% !important; top: 0; }for(var category in array[i]){... No tiene que iterar a través de las entradas de cada objeto, ya que eso agregará elementos innecesarios a la matriz como en su salida 'melon', 'melon', 'melon'
Puedes usar Array.prototype.reduce :
const itemData = [ { category: 'fruit', itemName: 'apple', onSale: false }, { category: 'canned', itemName: 'beans', onSale: false }, { category: 'canned', itemName: 'corn', onSale: true }, { category: 'frozen', itemName: 'pizza', onSale: false }, { category: 'fruit', itemName: 'melon', onSale: true }, { category: 'canned', itemName: 'soup', onSale: false }, ]; const object = itemData.reduce((acc,el) => (acc[el.category] ??= [], acc[el.category].push(el.itemName + (el.onSale ? '($)' : '')), acc), {}) console.log(object)