【もりけん塾】言語チャレンジ@iteratorについて

JavaScript

もりけん塾で JavaScriptの言語チャレンジに 取り組んでいます

課題は inputの値をoutputの値として出力することです
関数の引数に inputの値を渡し、実行した結果をconsole.logで示します

ここではoutputの値が、課題で提示されている通りになっていれば クリアとなります
つまり、ベストな書き方でなくても OKとなります

課題28

Remove “not”, “so” element. not use Iterator method(map, forEach,…etc) and Iterator(for, while)

input

['today', 'was', 'not', 'so', 'great']

output

[['today', 'was', 'great'], ['not', 'so']]

iteratorって聞いたことがあるけど、説明できないな…

iteratorとは

オブジェクトの内容を列挙するための仕組みを備えたオブジェクト。
Symbol.iterator()で返されるオブジェクトで各要素にアクセスするためのnext()を提供してくれる

const hoge = [1, 2, 3, 4, 5];
const iterator = hoge[Symbol.iterator]();
console.log(iterator);

具体的には以下の様な内容のオブジェクトをもつ

 next() {  // done,valueを含むオブジェクトが返される必要がある
   return {
    done: [true | false], // 反復の終了を表す(true -> 反復終了)
    value: value | undefined // 反復ごとに取得したい値(なければundefinedがかえる)
    }
 }

iterableとは

Symbol.iteratorのキーをもつデータ構造(オブジェクト)のこと
ex.) String, Array…などなど

Objectはiteratorを持っていない為、反復処理をすると以下の様なエラーが出る

const user = {
  name: "taro",
  age: 18,
  gender: "man",
};

for (const a of user) {
  console.log(a);
}

// Uncaught TypeError: user is not iterable

何度か見かけたUncaught TypeError: ** is not iterable は iterableではないことを教えてくれていたのか…

iteratorをつくってみる

先程のオブジェクトにiteratorを追加し、反復処理をしてuser情報を取り出してみる

Symbol.iterator プロパティに対してiteratorを設定することが必要

user[Symbol.iterator] = function () {
  let userKeys = Object.keys(this); // userのkeyを列挙した配列
  let index = 0;   // 現在のindex
  return {
    next: () => {
      if (index > userKeys.length - 1) {
        return {
          value: undefined,
          done: true,
        };
      }

      const userData = this[userKeys[index]];
      index++;
      return {
        value: userData,
        done: false,
      };
    },
  };
};

for (const data of user) {
  console.log(data);
}

再帰関数

今回はmapやforEach…forなども使用しないで書くような縛りがあるので
再帰関数でかきました

const input = ['today', 'was', 'not', 'so', 'great'];
const f = (parma) => {
  let i = 0;
  let removed = [];
  let result = [...parma];

  const func = (value) => {
    if (value === 'not' || value === 'so') {
      removed.push(value);
      result.splice(i, i);
    }
    if (i < parma.length - 1) {
      i++;
      func(parma[i]);
    }
  };

  func(parma[i]);
  return [result, removed];
};

console.log(f(input));

参考記事

JavaScript iterators and generators: A complete guide - LogRocket Blog
With the introduction of ES6 comes iterators and generators in JavaScript. This guide will teach you everything you need to know about them.
反復処理プロトコル - JavaScript | MDN
反復処理プロトコルは、新しい組み込みオブジェクトや構文ではなくプロトコルです。これらのプロトコルは以下のような単純な約束事によって、すべてのオブジェクトで実装することができます。
JavaScript Iterators and Iterables
In this tutorial, you will learn about JavaScript iterators and iterables with the help of examples.

まとめ

今回は縛りがあったので中々に苦戦しました…
ですがiteratorについて学ぶきっかけになり、どのように反復処理がされているかを理解することができました。

タイトルとURLをコピーしました