Почему я получаю "неопределенный" после нескольких итераций? - PullRequest
0 голосов
/ 27 апреля 2018

Странная вещь происходит с моим кодом ниже. Код работает гладко только с одним исключением - после нескольких итераций я получаю «неопределенный».

Вы можете проверить это, запустив его несколько раз. Сначала вы получите обычный вывод (три случайных города), а затем в какой-то момент вы получите «неопределенный». Это происходит менее чем за 10 итераций.

Почему он это делает? Что мне не хватает?

var coolWords = ["Amsterdam", "Berlin", "Sofia", "Prague", "Lisbon", "London", "Malaga", "Copenhagen", "Milan"];
    
var newList = [];
    
function niceTripleCombo(coolWords) {
  for (let i = 0; i < 3; i++) {
    var combo = coolWords[Math.floor(Math.random()*coolWords.length)];
    newList.push(" " + combo);
  };
};
    
function iterator(x) {
  if (newList[0] !== newList[1] && newList[1] !== newList[2] && newList[1] !== newList[3]) {
    return newList;
  } else {
    return niceTripleCombo(coolWords);
  }
};
    
    console.log(iterator(niceTripleCombo(coolWords)));

Ответы [ 4 ]

0 голосов
/ 27 апреля 2018

Давайте рассмотрим этот тестовый прогон.

Инициально, iterator(niceTripleCombo(coolWords)) вызывается с console.log().

Теперь niceTripleCombo(coolWords) будет вызываться.

Начало niceTripleCombo (coolWords)

Теперь в цикле,

i = 0, предположим, что мы получаем newList = [" Milan"]

i = 1, предположим, что мы получаем newList = [" Milan", " London"]

i = 2, предположим, что мы получаем newList = [" Milan", " London", " London"]

Конец niceTripleCombo (coolWords)

В конце мы имеем Милан, Лондон, Лондон

Сейчас в iterator(),

Так как у нас 2 Лондона, if не удастся и else будет запущен.

Теперь вот 1-я ошибка , вы не инициализировали newList для очистки. Поэтому, когда niceTripleCombo будет запущен снова, он добавит еще три города.

И вы можете получить, например, [" Milan", " London", " London", " Amsterdam", " Malaga", " Sofia"]

Теперь во вторых , return niceTripleCombo(coolWords); не вернет никакого значения.

Почему он ничего не возвращает, потому что вы возвращаете функцию [niceTripleCombo(coolWords)], у которой нет оператора возврата.

Либо ваша функция должна возвращать любое значение , либо при возврате функция, эта функция должна возвращать значение. В твоем случае, у вас нет оператора возврата в niceTripleCombo(coolWords) и по умолчанию функция js возвращает undefined, если нет другого значения вернулся.

Вот почему вы получаете undefined.

Итак, измените ваш else в вашем iterator следующим образом:

else {
  newList = [];
  niceTripleCombo(coolWords);
  return iterator();
}

Теперь вы не должны получать undefined. Далее нет необходимости передавать niceTripleCombo в iterator. Поскольку вы не используете функцию niceTripleCombo внутри вас iterator.

Подробнее о return в MDN: заявление о возврате

0 голосов
/ 27 апреля 2018

newList массив должен быть возвращен в методе niceTripleCombo.

var coolWords = ["Amsterdam", "Berlin", "Sofia", "Prague", "Lisbon", "London", "Malaga", "Copenhagen", "Milan"];

var newList = [];

function niceTripleCombo(coolWords) {
  newList.length = 0; // Empty the array before starting
  for (let i = 0; i < 3; i++) {
    var combo = coolWords[Math.floor(Math.random()*coolWords.length)];
    newList.push(" " + combo);
  };
  return newList; //Returning an array.
};

function iterator(x) {
  if (newList[0] !== newList[1] && newList[1] !== newList[2] && newList[1] !== newList[3]) {
    return newList;
  } else {
    return niceTripleCombo(coolWords);
  }
};

console.log(iterator(niceTripleCombo(coolWords)));
0 голосов
/ 27 апреля 2018

Пара примечаний к вашему коду:

  • Вы не перебираете все, вы просто проверяете один раз
  • Если в результате получится уникальное трио слов, этот метод будет тратить много циклов, если рандомизатор не даст вам правильные числа.
  • Если вы передаете массив, зачем делать его глобальной переменной? Это сделает ваш итератор бессмысленным.
  • Угадаемая функция не имеет возвращаемого значения - поэтому она возвращает undefined.

Мое предложение будет следующим:

var coolWords = ["Amsterdam", "Berlin", "Sofia", "Prague", "Lisbon", "London", "Malaga", "Copenhagen", "Milan"];

function niceTripleCombo( list ) {

  // Make a copy of the list so we don't modify the original.
  let words = list.slice();
  let result = [];
  
  for( let i = 0; i < 3; i++ ){
    
    // Use splice to get a word out of your copy array
    // It also removes it from the array,
    // so next time we cannot guess this word anymore.
    result.push(
      words.splice( Math.floor( Math.random() * words.length ), 1 )[ 0 ]
    );
    
  }
  
  return result;
  
};

console.log( niceTripleCombo(coolWords) );

Это всегда будет возвращать список из трех уникальных слов, и он делает это, выбирая случайное слово из массива, удаляя его из массива и добавляя его к ответу, а затем повторяя с теперь более коротким массивом. Таким образом, вам нужно только запустить этот цикл три раза вместо, возможно, бесконечной суммы, если рандомизатор не на вашей стороне.

0 голосов
/ 27 апреля 2018

Когда ваш массив newList имеет следующие значения,

 [" Berlin", " Berlin", " London"]

или аналогичный, если один из элементов массива совпадает, ваше условие if в итераторе не выполняется, и вы выполняете

niceTripleCombo(coolWords)

, который не имеет возвращаемого значения, следовательно, возвращает неопределенное значение.

...