最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Making a linked list iterable in ES6 - Stack Overflow

programmeradmin1浏览0评论

I have a linked list in JavaScript that I need to make iterable with a for of loop. I have almost done it but there seems to be no way to get the first value included in the result. Here is a simplified version:

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)

I have a linked list in JavaScript that I need to make iterable with a for of loop. I have almost done it but there seems to be no way to get the first value included in the result. Here is a simplified version:

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)
Share Improve this question edited Feb 16, 2017 at 23:50 castletheperson 33.5k11 gold badges74 silver badges107 bronze badges asked Feb 16, 2017 at 23:26 DidexeDidexe 1281 silver badge8 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

The problem is you're moving current to the next node before retrieving the value.

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);
}

It's much easier to implement an iterator with a generator function.

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);
}

You should be testing for current, not 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};
      }
    }
  };
}

But can write it much simpler as a generator method:

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

Btw, I would remend not putting this iterator on every node of the list (or even on the first one). Put in on a separate object that points to the head of the list, or make it a static helper function:

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;
  } 
}
发布评论

评论列表(0)

  1. 暂无评论