在ES6中使链表可迭代

7

我有一个JavaScript中的链表,我需要使用for of循环使其可迭代。我几乎做到了,但似乎没有办法将第一个值包含在结果中。这里是一个简化版本:

var obj = {value: 1, next: {value: 2, next: {value: 3, next: {value: 4, next: {value: 5, next: {value: 6, next: {value:7, next: null}}}}}}};

obj[Symbol.iterator] = function() {
  var current = this;
  return {
    next() {
      if (current.next !== null) {
        current = current.next;
        return {value: current.value, done: false};
      }
      return {done: true}
    }
  }
}

for (const x of obj) {
  console.log(x)
}

// this is how you get the values printed with no loop
// console.log(obj.value + '->' + obj.next.value + '->' + obj.next.next.value)
2个回答

6
问题在于你在获取 value 之前就将 current 移动到了下一个节点。

var obj = {value: 1, next: {value: 2, next: {value: 3, next: {value: 4, next: {value: 5, next: {value: 6, next: {value:7, next: null}}}}}}};

obj[Symbol.iterator] = function() {
  var current = this;
  return {
    next() {
      if (current) {
        var value = current.value;
        current = current.next;
        return {value: value, done: false};
      }
      return {done: true};
    }
  };
};

for (const x of obj) {
  console.log(x);
}

使用生成器函数实现迭代器更为容易。

var obj = {value: 1, next: {value: 2, next: {value: 3, next: {value: 4, next: {value: 5, next: {value: 6, next: {value:7, next: null}}}}}}};

obj[Symbol.iterator] = function*() {
  var current = this;
  while (current) {
    yield current.value;
    current = current.next;
  }
};

for (const x of obj) {
  console.log(x);
}


1
你应该测试current,而不是current.next:
obj[Symbol.iterator] = function() {
  var current = this;
  return {
    next() {
      if (current !== null) {
        var res = {value: current.value, done: false};
        current = current.next;
        return res;
      } else {
        return {done: true};
      }
    }
  };
}

但是可以将它写成一个生成器方法,更简单易懂:

obj[Symbol.iterator] = function* () {
  for (var current = this; current !== null; current = current.next) {
    yield current.value;
  }
}

顺便说一下,我建议不要将这个迭代器放在列表的每个节点上(甚至不要放在第一个节点上)。将其放在指向列表头部的单独对象上,或者将其作为静态辅助函数:

let list = {
  head: obj, // could be null either
  *[Symbol.iterator]() {
    for (var current = this.head; current !== null; current = current.next) {
      yield current.value;
    }
  }
}

function* linkedList(head)
  for (; head !== null; head = head.next) {
    yield head.value;
  } 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接