Tengo un formulario en el que puedo crear secciones duplicadas. En este momento, cuando se envía el formulario, el formulario escupe un objeto gigante. Estoy trabajando en una función de filtro que puede filtrar las secciones duplicadas y organizar los duplicados en una matriz para que funcione con mi API.
p.ej
// objeto básico
{ question_10: "" question_10a: "" question_11_checkbox: false question_11_checkbox_copy_0: false question_11_checkbox_copy_1: true question_11_text: "110 Monroe St" question_11_text_copy_0: "186 Aspen Road" question_12_checkbox: false question_12_checkbox_copy_0: false question_12_text: "New York" question_12_text_copy_0: "South Orange" ... }// lo que quiero es
{ question_10: "" question_10a: "" question_11_checkbox: false question_11_checkbox_copies: [ { question_11_checkbox_copy_0: false } { question_11_checkbox_copy_1: true } ] question_11_text: "101 Monroe St" question_11_text_copies: [ { question_11_text_copy_0: "186 Aspen Road"} ] question_12_checkbox: false question_12_checkbox_copies: [ { question_12_checkbox_copy_0: false} ] question_12_text: "New York" question_12_text_copies: [ { question_12_text_copy_0: "South Orange"} ] ... }Hasta ahora he podido filtrar las copias del objeto original y crear las matrices para las copias.
// filter out copy keys const copiesKey = Object.keys(data).filter(key => key.includes('copy')); const copy = {}; // create arrays for copies copiesKey.map(copiedQuestion => { if (!(`${copiedQuestion.slice(0, copiedQuestion.length - 7)}_copies` in copy)) { copy[`${copiedQuestion.slice(0, copiedQuestion.length - 7)}_copies`] = []; } });Donde estoy atascado es que no está claro cómo hacer coincidir el objeto con la matriz adecuada y empujarlo. p.ej
question_11_text_copies: [ { question_11_text_copy_0: "186 Aspen Road" } ]Hasta ahora, he intentado dividir las últimas tres claves del objeto copy_0 y hacer coincidir la clave con el nombre de la matriz usando array.filter, pero eso no funcionó como se esperaba.
¿Cómo puedo hacer coincidir los objetos 'copy_n' con la matriz adecuada y enviar esos objetos a la matriz?
Puede reducir las entradas del objeto a un nuevo objeto. Para cada clave, busque si tiene una clave base (la que está antes de " copiar ") usando RegExp con anticipación. Si no tiene una clave base, agréguela directamente al acumulador. Si es así, agréguelo a la matriz de "copias" adecuada (inícielo si es necesario usando la asignación lógica nula ??= ) ( TS playground ).
const fn = obj => Object.entries(obj) .reduce((acc, [k, v]) => { const [baseKey] = k.match(/.*(?=_copy_)/) ?? [] // get the key from an item with copy if(!baseKey) acc[k] = v // if no baseKey add the item to the accumulator else { const copiesKey = `${baseKey}_copies` acc[copiesKey] ??= [] // if no copies key add a new one to the accumulator acc[copiesKey].push({ [k]: v }) // create an object and push to the current copies key } return acc }, {}) const obj = {"question_10":"","question_10a":"","question_11_checkbox":false,"question_11_checkbox_copy_0":false,"question_11_checkbox_copy_1":true,"question_11_text":"110 Monroe St","question_11_text_copy_0":"186 Aspen Road","question_12_checkbox":false,"question_12_checkbox_copy_0":false,"question_12_text":"New York","question_12_text_copy_0":"South Orange"} const result = fn(obj) console.log(result)Esto puede ser un poco anticuado, pero usar un bucle for...in en combinación con la coincidencia de patrones de expresiones regulares con la clave podría ser la solución más clara.
const data = { question_10: "", question_10a: "", question_11_checkbox: false, question_11_checkbox_copy_0: false, question_11_checkbox_copy_1: true, question_11_text: "110 Monroe St", question_11_text_copy_0: "186 Aspen Road", question_12_checkbox: false, question_12_checkbox_copy_0: false, question_12_text: "New York", question_12_text_copy_0: "South Orange", }; const copy_n = /^(.*)_copy_(\d+)$/; const result = {}; for (const key in data) { const value = data[key]; const match = key.match(copy_n); if (match) { const copies_key = `${match[1]}_copies`; const index = parseInt(match[2], 10); result[copies_key] ||= []; result[copies_key][index] = { [key]: value }; } else { result[key] = value; } } console.log(result); El patrón /^(.*)_copy_(\d+)$/ coincide con cualquier cosa que termine con _copy_ seguido de 1 o más decimales. Todo antes _copy_ se coloca en el grupo de captura 1, los decimales detrás de _copy_ se colocan en el grupo de captura 2.
Si no hay ninguna coincidencia (en caso contrario ), simplemente asignamos el valor a la misma clave.
Si hay una coincidencia ( si el escenario) primero determinamos la clave de colección ( copies_key ) y el índice a usar. Luego verificamos si result[copies_key] ya está configurado (verificamos si es un valor real para ser precisos). Si no es así, lo asignamos a una matriz vacía. Después de eso, usamos el index para asignar un objeto al índice correcto en la matriz.