Tengo una variedad de objetos.
listOfItems: any[] = [ {text: 'Hola', group: 'espanian'}, {text: 'Hello', group: 'english'}, {text: 'How are you', group: 'english'}, {text: 'Tere', group: 'estonian'}, ]Me gustaría iterar sobre una matriz y crear otra matriz con objetos categorizados
groups: any[] = [ [ { name: 'english', items: [ {text: 'Hello', group: 'english'}, {text: 'How are you', group: 'english'}, ] }, { name: 'espanian', items: [ {text: 'Hola', group: 'espanian'} ] }, { name: 'estonian', items: [ {text: 'Tere', group: 'estonian'} ] }, ]¿Cuál es la forma más dinámica de hacerlo? La cantidad de grupos podría ser superior a 30, por lo que me gustaría evitar hacer comprobaciones si o iguales dentro del bucle.
Me refiero a dinámico: básicamente no tiene controles explícitos como item.group = 'english'
He intentado lograr algo similar con
let result: any = []; this.listOfItems.forEach(p => { var key = p.group; result[key] = result[key] || []; result[key].push(p); })sin embargo, el resultado no es exactamente lo que estoy buscando.
[ {'english': [ {text: 'Hello', group: 'english'}, {text: 'How are you', group: 'english'}, ] }, {'espanian': [ {text: 'Hola', group: 'espanian'}, ] }, ]Implementación Array.reduce .
const listOfItems = [ { text: 'Hola', group: 'espanian' }, { text: 'Hello', group: 'english' }, { text: 'How are you', group: 'english' }, { text: 'Tere', group: 'estonian' }, ]; const output = listOfItems.reduce((acc, curr) => { const matchItem = acc.find(item => item.name === curr.group); if (matchItem) { matchItem.items.push(curr); } else { acc.push({ name: curr.group, items: [curr] }) } return acc; }, []); console.log(output);Para aquellos que están preocupados por el doble bucle, puede lograr el anterior con un solo bucle usando.
const listOfItems = [ { text: 'Hola', group: 'espanian' }, { text: 'Hello', group: 'english' }, { text: 'How are you', group: 'english' }, { text: 'Tere', group: 'estonian' }, ]; const output = listOfItems.reduce((acc, curr) => { acc[curr.group] ? acc[curr.group].items.push(curr) : acc[curr.group] = { name: curr.group, items: [curr] }; return acc; }, {}); console.log(Object.values(output));any[] ? interface Item { text: string; group: string; } interface Categorized { name: string; items: Item[]; } const itemList: Item[] = [ { text: 'Hola', group: 'espanian' }, { text: 'Hello', group: 'english' }, { text: 'How are you', group: 'english' }, { text: 'Tere', group: 'estonian' }, ]; const categorize = (list: Item[]): Categorized[] => { const map: Record<string, Categorized> = {}; list.forEach((item) => { if (!map[item.group]) { map[item.group] = { name: item.group, items: [item] }; return; } map[item.group].items.push(item); }); return Object.values(map); }; console.log(categorize(itemList));Solo estamos usando un bucle.
compilado:
var itemList = [ { text: 'Hola', group: 'espanian' }, { text: 'Hello', group: 'english' }, { text: 'How are you', group: 'english' }, { text: 'Tere', group: 'estonian' }, ]; var categorize = function (list) { var map = {}; list.forEach(function (item) { if (!map[item.group]) { map[item.group] = { name: item.group, items: [item] }; return; } map[item.group].items.push(item); }); return Object.values(map); }; console.log(categorize(itemList));Prueba con el siguiente código
const modifiedList = listOfItems.reduce((acc, item) => { if(!acc[item.group]) acc[item.group]=[item]; else acc[item.group].push(item); return acc; }, {}); let newList = []; for(let item in modifiedList) { newList.push({ name: item, items: modifiedList[item] }) }