Node.js: объединение forEach () с ранним возвратом - PullRequest
0 голосов
/ 25 ноября 2018

Моя проблема

Политика ESLint airbnb запрещает for...of повторений цикла и предпочитает forEach((element) => { code });.Однако внутренние возвраты из этого цикла проглатываются - они считаются returns анонимной функции, а не функцией, охватывающей цикл.

Код

Оригинал

Работает, но ломает eslint-config-airbnb .

const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey'];

const MIN_WORD_SIZE = 4;
const MAX_WORDS = 3;

function NestedIterator1() {
  const wordlist = [];
  for (const word of words) {
    if (word.length >= MIN_WORD_SIZE) {
      wordlist.push(word);
    }
    if (wordlist.length >= MAX_WORDS) {
      return wordlist;
    }
  }
  return wordlist;
}

console.log(NestedIterator1());

Альтернатива 1: итерация индексов массива

Работает, но стиль устарел, и мне приходится вручную присваивать значения индексам.

const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey'];

const MIN_WORD_SIZE = 4;
const MAX_WORDS = 3;


function NestedIterator2() {
  const wordlist = [];
  for (let i = 0; i < words.length; i += 1) {
    const word = words[i];
    if (word.length >= MIN_WORD_SIZE) {
      wordlist.push(word);
    }
    if (wordlist.length >= MAX_WORDS) {
      return wordlist;
    }
  }
  return wordlist;
}


console.log(NestedIterator2());

Альтернатива 2: использование forEach

Придерживается руководства по стилю, но не работает - внутренние возвраты считаются возвращениями из анонимной функции,а не NestedIterator3.

const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey'];

const MIN_WORD_SIZE = 4;
const MAX_WORDS = 3;

function NestedIterator3() {
  const wordlist = [];
  words.forEach((word) => {
    if (word.length >= MIN_WORD_SIZE) {
      wordlist.push(word);
    }
    if (wordlist.length >= MAX_WORDS) {
      return wordlist;
    }
  });
  return wordlist;
}

console.log(NestedIterator3());

Мой вопрос

Как функция может выполнять итерацию по массиву, позволяя досрочно возвращаться, избегая индексов и for..of итераций?

1 Ответ

0 голосов
/ 25 ноября 2018

Одним из вариантов будет использование reduce, которое очень гибкое и может использоваться во многих ситуациях, когда другие методы итерации недостаточны - только push для аккумулятора, если длина аккумулятора меньше MAX_WORDS и длины слова достаточно:

const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey'];

const MIN_WORD_SIZE = 4;
const MAX_WORDS = 3;

function NestedIterator3() {
  return words.reduce((wordlist, word) => {
    if (wordlist.length < MAX_WORDS && word.length >= MIN_WORD_SIZE) {
      wordlist.push(word);
    }
    return wordlist;
  }, []);
}

console.log(NestedIterator3());

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

const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey'];

const MIN_WORD_SIZE = 4;
const MAX_WORDS = 3;

function NestedIterator3() {
  const wordlist = [];
  words.some((word) => {
    if (word.length >= MIN_WORD_SIZE) {
      wordlist.push(word);
    }
    return wordlist.length === MAX_WORDS;
  }, []);
  return wordlist;
}

console.log(NestedIterator3());

Для этого конкретного примера вы также можете использовать filter, за которым следует slice:

const words = ['harry', 'potter', 'and', 'the', 'forbidden', 'journey'];

const MIN_WORD_SIZE = 4;
const MAX_WORDS = 3;

function NestedIterator3() {
  return words
    .filter(word => word.length >= MIN_WORD_SIZE)
    .slice(0, MAX_WORDS)
}

console.log(NestedIterator3());

, что, безусловно, выглядит гораздо более элегантно, но .filter сначала обязательно перебирает все элементы в массиве, и поэтому имеет ту же проблему, что и reduce (нетпроисходит короткое замыкание) - кроме того, эти два сцепленных метода представляют только подмножество ситуаций, в которых может возникнуть необходимость в коротком замыкании итерации массива.

...