Im totalmente ni idea de cómo construir esto. Ni siquiera estoy seguro de que sea posible y me he estado rascando la cabeza durante demasiado tiempo.
Digamos que tengo un objeto:
const myObj = { simple: "test", nested: { obj: "alright" } }Ahora encontré una función que me permite establecer un valor en cualquier lugar especificando una ruta en ese árbol. Si aún no existe una clave en ese objeto, se creará:
const set = (obj: any, path: any, val: any) => { const keys = path.split("."); const lastKey = keys.pop(); const lastObj = keys.reduce((obj: any, key: any) => obj[key] = obj[key] || {}, obj); lastObj[lastKey] = val; };Ejemplo:
set(myObj, "nested.another.iCanEvenGoDeeper", "very deep value");Resultado:
const myObj = { simple: "test", nested: { obj: "alright", another: { iCanEvenGoDeeper: "very deep value" } } }Hasta ahora todo bien, pero ahora se requiere que también pueda definir una ruta como esta para construir matrices dinámicamente. Para que pueda llamar a estos:
set(myObj, "nested.myArray[0].propInsideArrayElement", "first element") set(myObj, "nested.myArray[1].propInsideArrayElement", "second element")eso dará como resultado un objeto que se ve así:
{ simple: "test", nested: { obj: "alright", myArray: [ { propInsideArrayElement: "first element" }, { propInsideArrayElement: "second element" } ] } }Debe ser recursivo y funcionar con todos los escenarios, pero como dije, no tengo ni idea de si es posible. ¿Existe por casualidad algún script de utilidad que ya haga esto? Si no, ¿alguien puede indicarme la dirección correcta?
En el próximo paso, me gustaría aplanar el objeto para tener un objeto unidimensional nuevamente, para el último ejemplo, se vería así:
flatten(myObj);luego se volvería a
{ "simple": "test", "nested.obj": "alright", "nested.myArray[0].propInsideArrayElement": "first element", "nested.myArray[1].propInsideArrayElement": "second element" }Parece interesante :)
Aquí hay un ejemplo de soporte de matriz basado en su propio código.
aplanar el objeto también está incluido (usando llamadas recursivas)
const myObj = { simple: "test", nested: { obj: "alright" } } const getTypeVal = (currentIndex, length, val) => { } const set = (obj, path, val) => { path = path.replace('[', '.[') const keys = path.split("."); const lastKey = keys.pop(); let lastObj = keys.reduce((obj, key, currentIndex) => { if(key.includes('[')) { return obj[key.substring(1, key.length-1)] } if(obj[key] && obj[key].length && (keys[currentIndex+1] && keys[currentIndex+1].includes('['))) { let nextKey = keys[currentIndex+1] nextKey = nextKey.substring(1, nextKey.length-1) !obj[key][nextKey] && obj[key].push({}) } return obj[key] = obj[key] || ((keys[currentIndex+1] && keys[currentIndex+1].includes('[')) ? [{}] : keys[currentIndex+1] ? {} : val) } , obj); lastObj[lastKey] = val; }; const flatternObj = (obj, result = {}, key ='') =>{ if(Array.isArray(obj)) { obj.forEach((d,i) => { result = flatternObj(d, result, key + `[${i}]`) }) } else if(typeof obj === 'object') { for (const i of Object.keys(obj)) { result = flatternObj(obj[i], result, key ? key + `.${i}` : `${i}`) } } else { result[key] = obj } return result; } set(myObj, "nested.myArray[0].propInsideArrayElement", "first element") set(myObj, "nested.myArray[0].propInsideArrayElement2", "first element - 2 ") set(myObj, "nested.myArrayTwo[0]", 'test') set(myObj, "nested.myArray[1].propInsideArrayElement", "second element") set(myObj, "nested.myArray[2]", 'test') console.log(myObj) console.log(flatternObj(myObj))He reelaborado totalmente la función deepSet ahora. Ahora admite múltiples matrices y espacios en las matrices, etc. Creo que ahora cubre todos los casos de uso. Al final, fue mucho más fácil descifrar la lógica cuando comencé de nuevo sin la función de reducción.
export const deepSet = (obj: any, path: string, val: any) => { path = path.replaceAll("[", ".["); const keys = path.split("."); for (let i = 0; i < keys.length; i++) { let currentKey = keys[i] as any; let nextKey = keys[i + 1] as any; if (currentKey.includes("[")) { currentKey = parseInt(currentKey.substring(1, currentKey.length - 1)); } if (nextKey && nextKey.includes("[")) { nextKey = parseInt(nextKey.substring(1, nextKey.length - 1)); } if (typeof nextKey !== "undefined") { obj[currentKey] = obj[currentKey] ? obj[currentKey] : (isNaN(nextKey) ? {} : []); } else { obj[currentKey] = val; } obj = obj[currentKey]; } };