Necesito contar las vocales en una matriz anidada y me gustaría hacerlo con el cierre para evitar la contaminación global del espacio de nombres. Aquí está mi código:
let nestedArr = [ "Elie", ["Matt", ["Tim"]], ["Colt", ["Whiskey", ["Janey"], "Tom"]], "Lorien" ]; function countVowels() { let vowelsCount = 0; let vowels = ['a', 'e', 'i', 'o', 'u']; return function foo(arr) { for (let i = 0; i < arr.length; i++) { if (typeof arr[i] === 'string') { for (let letter of arr[i]) { if (vowels.includes(letter.toLowerCase())) { vowelsCount++; } } } else { return foo(arr[i]); } } return vowelsCount; } } const counter = countVowels(); console.log(counter(nestedArr));Espero el número correcto de vocales, pero obtuve 5. Traté de depurar y veo que simplemente se detiene después de "Tim", que es el subarreglo más profundo, por lo que obviamente mi función no sube de nivel y me falta algo.
¿Cómo puedo conseguir esto?
Gracias de antemano.
No necesita la función anidada, puede declarar una sola función recursiva y aún así mantener todo autónomo.
const countVowels = (arr) => { const vowels = ['a', 'e', 'i', 'o', 'u']; const vowel_count = (s) => [...s].filter((c) => vowels.includes(c.toLowerCase())).length; let vowels_total = 0; for (const e of arr) { vowels_total += Array.isArray(e) ? countVowels(e) : vowel_count(e); } return vowels_total; }; const nestedArr = ['Elie', ['Matt', ['Tim']], ['Colt', ['Whiskey', ['Janey'], 'Tom']], 'Lorien']; console.log(countVowels(nestedArr)); O bien, renunciar a la recursividad con un cierre curry usando Array#flat() (a Infinity )
const countVowels = ( (v) => (arr) => [...arr.flat(Infinity).join('')].filter((c) => v.includes(c.toLowerCase())).length )(['a', 'e', 'i', 'o', 'u']); const nestedArr = ['Elie', ['Matt', ['Tim']], ['Colt', ['Whiskey', ['Janey'], 'Tom']], 'Lorien']; console.log(countVowels(nestedArr));Su función funciona bien si solo cambia
return foo(arr[i]);A:
foo(arr[i]);Debe dejar que se ejecute todo el ciclo (obviamente), el retorno hace que se detenga antes.
let nestedArr = [ "Elie", ["Matt", ["Tim"]], ["Colt", ["Whiskey", ["Janey"], "Tom"]], "Lorien" ]; function countVowels() { let vowelsCount = 0; let vowels = ['a', 'e', 'i', 'o', 'u']; return function foo(arr) { for (let i = 0; i < arr.length; i++) { if (typeof arr[i] === 'string') { for (let letter of arr[i]) { if (vowels.includes(letter.toLowerCase())) { vowelsCount++; } } } else { foo(arr[i]); } } return vowelsCount; } } const counter = countVowels(); console.log(counter(nestedArr));Esto suena principalmente como un ejercicio para aprender recursividad. Si es así, te dejo con las otras buenas respuestas recursivas aquí.
Pero una alternativa simple es observar el formato toString para Arrays y darnos cuenta de que podemos simplemente aplicar nuestras pruebas al resultado de eso, dejando un código muy simple:
const countVowels = (a) => [... a .toString () .toLowerCase ()] .filter (c => 'aeiou' .includes (c)) .length const nestedArr = ['Elie', ['Matt', ['Tim']], ['Colt', ['Whiskey', ['Janey'], 'Tom']], 'Lorien'] console .log (countVowels (nestedArr))