¿Cómo filtrar una matriz anidada? Tengo una matriz con usuarios, necesito mostrar los roles del usuario seleccionado en , pero resulta ser un gran anidamiento y un montón de iteraciones, cómo evitar esto y obtener algo como:
const options = [ { value: 1, label: "admin" }, { value: 0, label: "moderator" } ];hago
const arr = [ { users: [ { id: 1, login: "alex", roles: [ { id: 0, name: "admin" }, { id: 1, name: "moderator" } ] }, { id: 2, login: "bob", roles: [{ id: 0, name: "viewer" }] } ] } ]; const rolesOptions = arr.filter(({ users }) => users .filter(({ id }) => id === 1) .map(({ roles }) => roles.map(({ id, name }) => ({ label: name, value: id })) ) ); console.log(rolesOptions);Puede usar .flatMap() para mapear su arr exterior del objeto. Para cada objeto anidado interno, puede filtrarlo para mantener solo los objetos que coincidan con la id de 1 (como lo ha hecho). Luego puede usar .flatMap() en la matriz interna filtrada para asignar cada rol a su objeto con clave nueva con label y name . Los métodos .flatMap() luego combinan los resultados de la matriz devuelta en una matriz resultante:
const arr = [ { users: [ { id: 1, login: "alex", roles: [ { id: 0, name: "admin" }, { id: 1, name: "moderator" } ] }, { id: 2, login: "bob", roles: [{ id: 0, name: "viewer" }] } ] } ]; const options = arr.flatMap(({users}) => users .filter(({ id }) => id === 1) .flatMap(({roles}) => roles.map(({ id, name }) => ({ label: name, value: id }))) ); console.log(options); Si sabe con certeza que solo puede haber un objeto de usuario dentro de la matriz de users de cada objeto con una id dada, entonces puede hacer que su código sea más eficiente usando .find() para que regrese tan pronto como el usuario del objeto con la identificación es encontrado:
const arr = [{ users: [{ id: 1, login: "alex", roles: [{ id: 0, name: "admin" }, { id: 1, name: "moderator" }] }, { id: 2, login: "bob", roles: [{ id: 0, name: "viewer" }] }] }]; const options = arr.flatMap(({users}) => users .find(({ id }) => id === 1) ?.roles.map(({ id, name }) => ({ label: name, value: id })) ?? [] ); console.log(options); Lo anterior usa el encadenamiento opcional ( ?. ) para verificar que se puede encontrar un usuario con la identificación, y el operador de fusión nulo ( ?? ) para devolver una matriz vacía si no se pudo encontrar la id .
Necesitabas usar el map en lugar del filter en la matriz externa arr
flat luego aplana los objetos restantes
const arr = [ { users: [ { id: 1, login: "alex", roles: [ { id: 0, name: "admin" }, { id: 1, name: "moderator" } ] }, { id: 2, login: "bob", roles: [{ id: 0, name: "viewer" }] } ] } ]; const rolesOptions = arr.map(({ users }) => users .filter(({ id }) => id === 1) .map(({ roles }) => roles.map(({ id, name }) => ({ label: name, value: id })) ) ).flat(2); console.log(rolesOptions)Esto es lo que se me ocurrió:
const arr = [ { users: [ { id: 1, login: "alex", roles: [ { id: 0, name: "admin" }, { id: 1, name: "moderator" } ] }, { id: 2, login: "bob", roles: [{ id: 0, name: "viewer" }] } ] } ]; const users = getUsers(arr) const rolesOptions = getRolesOptions(users) console.log(rolesOptions) function getUsers(arr) { let res = [] // The result array arr .filter(({ users }) => users) // Filters to find every instance that has a "users" JSON key .map(({ users }) => users) // Maps out the users into multiple arrays .forEach(users => { // Adds each array of users into one array users.forEach(user => { res.push(user) }) }) return res } function getRolesOptions(users) { let res = [] // The result array users.forEach(user => { user.roles.forEach(({ name, id }) => { // For every user it pushes the role in formate { name, id } to the result array res.push({ label: name, value: id }) }) }) return res }Probablemente hay una manera más ordenada. Disculpa si no es lo que pediste