Поиск вложенных массивов гласных - PullRequest
0 голосов
/ 08 декабря 2018

Я написал 2 функции для поиска и подсчета гласных среди строк во вложенных массивах.Первая функция searchVowels выполняет фактический поиск и подсчитывает гласные.Вторая функция countVowels просто объявляет переменную vowels (counter), выполняет первую функцию и возвращает результат.Я должен был сделать это из-за рекурсивности первой функции, которая вызвала бы множество объявлений и возвратов переменной vowels.

Проблема в том, что даже если я объявлю vowels с ключевым словом var (область действия должна быть всей функцией), внутренняя функция searchVowels не увидит его.Если я возьму объявление из функции и сделаю vowels глобальным, все будет нормально.Поэтому мой вопрос: почему searchVowels не видит переменную vowels, объявленную с var в родительской функции?

var nestedArr = [
    "Elie",
    ["Matt", ["Tim"]],
    ["Colt", ["Whisky", ["Janey"], "Tom"]],
    "Lorien"
];


function searchVowels(arr) {
    //iterating through each element of the array (or nested arrays in the subsequent calls)
    for (let i of arr) {
        //checking if the element i of the array is a string or another array
        if (typeof i === 'string') {
            //looping through the elements of the string
            for(let j of i) {
                //checking if the current element of the string is a vocal or not
                if (j === 'a' || j === 'e' || j === 'i' || j === 'o' || j === 'u' || j === 'A' || j === 'E' || j === 'I' || j === 'O' || j === 'U') {
                    vowels++;
                } 
            }
        //if the element i of the parent array is another array, the function calls itself and repeats everything on the  nested array (recursive)
        } else searchVowels(i);
    }
}


function countVowels (arr) {
    var vowels = 0;
    searchVowels (arr);
    return vowels;
}

countVowels(nestedArr);

Ответы [ 3 ]

0 голосов
/ 08 декабря 2018

Проблема заключается в javascript область видимости блока.

Вот совершенно альтернативный способ сделать этот код:

/**
* All vowels in lowercase
*/
const vowels = ["a", "e", "i", "o", "u"]

/**
* Check if a character is a vowel
*/
function isVowel(character) {
  return !!vowels.find(vowel => character.toLowerCase() === vowel)
}

/**
* Search for vowels in nested arrays
* Return a string of all the vowels concatenated
*/
function searchVowels(arr) {
  let result = ""

  for (const i of arr) {
    if (typeof i === "string") {
      for (const j of i) {
        if (isVowel(j)) {
          result += j.toLowerCase()
        }
      }
    }
    else result += searchVowels(i)
  }

  return result
}

/**
* Count the number of vowels in nested arrays
*/
function countVowels(arr) {
  return searchVowels(arr).length
}

/***************************************
***************************************/

const nestedArr = [
  "Elie",
  ["Matt", ["Tim"]],
  ["Colt", ["Whisky", ["Janey"], "Tom"]],
  "Lorien"
]

console.log(searchVowels(nestedArr))
//> "eieaioiaeooie"

console.log(countVowels(nestedArr))
//> 13

Теперь у каждой функции есть только одно задание -search гласные ищет и возвращает гласные, а затем подсчитывает гласные, подсчитывает результаты этого

Конечно, в этом новом случае эти две строки эквивалентны:

  1. const numberOfVowels = countVowels(arr)
  2. const numberOfVowels = searchVowels(arr).length

Функция подсчета гласных, таким образом, не нужна и должна быть полностью удалена

0 голосов
/ 08 декабря 2018

@ georg уже объяснил проблему определения объема.Просто для удовольствия я хотел бы представить альтернативную версию es6 / regex для подсчета гласных.

const nestedArr = [
    "Elie",
    ["Matt", ["Tim"]],
    ["Colt", ["Whisky", ["Janey"], "Tom"]],
    "Lorien"
];

console.log(countVowels(nestedArr));

function countVowels(nestedArr) {
  // note: only strings or arrays, otherwise empty string
  const flatten = value => {
    if (value.constructor === String) { return value; }
    return value.constructor === Array
     ? value.map( v => v.constructor === String ? v : flatten(v) ).join("")
     : "";
  };
  // note: included y (semivowel)
  return nestedArr
   .reduce( (s, v) => `${s}${flatten(v)}`, "")
   .match(/[aeiouy]/gi).length;
}
0 голосов
/ 08 декабря 2018

почему searchVowels не видит переменную vowels, объявленную с помощью var в родительской функции?

Поскольку Javascript - это язык со статической (лексической) областью и отношения функций родитель-потомокопределяется тем, как они написаны, а не тем, как они называются (это будет «динамическая» область видимости).

Чтобы все работало как задумано, вы должны поместить дочернюю функцию в родительский текст:

function countVowels (arr) {
    var vowels;

    function searchVowels(arr) {
        ...
    }
}

В общем, старайтесь избегать функций, которые изменяют внешние переменные или иным образом изменяют внешний мир («побочные эффекты»).Намного лучше проектировать свои функции «чистым» способом, чтобы они принимали только параметры и возвращаемые значения - точно так же, как математические функции.Пример:

function countVowels(arr) {
    let count = 0;

    for (let item of arr) {

        if (Array.isArray(item))
            count += countVowels(item)
        else
            for (let char of item.toUpperCase()) {
                if ('AEIOU'.includes(char)) {
                    count++
                }
            }
    }

    return count
}

Здесь каждая рекурсивная копия countVowels выделяет свой собственный локальный счетчик и возвращает его вызывающей стороне, которая затем заботится о добавлении его к своему собственному счетчику и так далее, до самого верхнегоуровень достигнут.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...