Estoy tratando de dividir una matriz de componentes en matrices individuales dependiendo de si hay una list que rompe el patrón de heading , paragraph u hr . Esto es lo que he intentado:
const components = [ { name: 'heading' }, { name: 'paragraph' }, { name: 'hr' }, { name: 'heading' }, { name: 'list' }, { name: 'hr' }, { name: 'paragraph' }, { name: 'list' } ]; const richText = []; const list = []; components.forEach((component, index) => { switch (component.name) { case 'heading': case 'hr': case 'paragraph': richText.push(component.name) break case 'list': list.push(`${component.name}-index`) break } }) console.log(richText)La salida actual es:
[ { name: 'heading' }, { name: 'paragraph' }, { name: 'hr' }, { name: 'heading' }, { name: 'hr' }, { name: 'paragraph' } ]La salida deseada es:
[ { name: 'heading' }, { name: 'paragraph' }, { name: 'hr' }, { name: 'heading' } ], [ { name: 'hr' }, { name: 'paragraph' } ]Teniendo en cuenta la list como un descanso, puede realizar la inicialización de richText como [[]] . Puede seguir presionando hasta el último index de richText hasta que se encuentre una list . Si se encuentra una list , inserte una matriz vacía [] en su matriz de richText .
violín de trabajo
const components = [ { name: 'heading' }, { name: 'paragraph' }, { name: 'hr' }, { name: 'heading' }, { name: 'list' }, { name: 'hr' }, { name: 'paragraph' }, { name: 'list' } ]; const richText = [[]]; const list = []; components.forEach((component, index) => { switch (component.name) { case 'heading': case 'hr': case 'paragraph': richText[richText.length - 1].push(component); break case 'list': list.push({name: `${component.name}-${richText.length}`}) index < components.length - 1 ? richText.push([]) : {}; break } }) console.log(richText); console.log(list); Misma lógica Array.reduce implementación
const components = [ { name: 'heading' }, { name: 'paragraph' }, { name: 'hr' }, { name: 'heading' }, { name: 'list' }, { name: 'hr' }, { name: 'paragraph' }, { name: 'list' } ]; const richText = components.reduce((acc, curr, index) => { if(curr.name === 'list' && index < components.length - 1) { acc.push([]); } else { acc[acc.length - 1].push(curr); } return acc; }, [[]]); console.log(richText);Qué tal si
const components = [ { name: 'heading' }, { name: 'paragraph' }, { name: 'hr' }, { name: 'heading' }, { name: 'list' }, { name: 'hr' }, { name: 'paragraph' }, { name: 'list' } ]; let richText = []; let list = []; components.forEach((component, index) => { switch (component.name) { case 'heading': case 'hr': case 'paragraph': richText.push({'name': component.name}) break case 'list': list.push(richText); richText = []; break } }) console.log(list);Aquí hay una función genérica similar a groupby de python. Dada una función iterable y clave, produce pares [key, chunk] donde cada chunk contiene elementos secuenciales que tienen la misma key :
function* groupBy(iter, keyFn) { let last = null, buf = [] for (let item of iter) { let key = keyFn(item) if (key !== last) { if (buf.length) yield [last, buf] buf = [] } buf.push(item) last = key } yield [last, buf] }Aplicado a su problema:
for (let [isList, tags] of groupBy(components, c => c.name === 'list')) if (isList) ... else ...