Nodejs 使用ES6 generator 实现链式API + lazy evaluation的数组迭代
Nodejs 使用ES6 generator 实现链式API + lazy evaluation的数组迭代
借助ES6 generator,写了一个小型迭代数组的库,可以像下面这样使用
//取1到10中的偶数,然后取这些偶数的平方
var _1to10 = [1,2,3,4,5,6,7,8,9,10];
var arr =iter(_1to10)
.where(function(v){return v%2==0})
.map(function(v){return v*v})
.toArray();
console.log(arr); // [4, 16, 36, 64, 100]
//对年龄大于20的人,按年龄进行排序
var person = [{first:'god',last:'pig',age:25,male:'m'},
{first:'wang',last:'er',age:26,male:'m'},
{first:'zhang',last:'san',age:18,male:'m'},
{first:'li',last:'si',age:19,male:'m'},
{first:'god',last:'pig',age:21,male:'m'},
{first:'god',last:'cat',age:22,male:'m'}];
var arr= iter(person)
.where(function(v){return v.age>20})
.sort(function(v1,v2){return v1.age-v2.age})
.toArray();
//arr:[{..age:21..} , ... , {..age:26}...]
我个人觉得这种用法很有吸引力,特别是加上lambda表达式后。https://github.com/jzlxiaohei/yield-iter上有更多demo,请大家拍砖
2 回复
Node.js 使用 ES6 Generator 实现链式 API + Lazy Evaluation 的数组迭代
借助 ES6 Generator,我们可以编写一个小型的库来迭代数组,并实现类似 jQuery 风格的链式调用。这种方式不仅简洁而且非常高效,因为它是惰性求值(lazy evaluation)的。
示例代码
function* iter(array) {
for (let item of array) {
yield item;
}
}
Array.prototype.where = function (predicate) {
let gen = iter(this);
return {
[Symbol.iterator]: function () {
return {
next: () => {
let result;
do {
result = gen.next();
} while (!result.done && !predicate(result.value));
return result;
}
};
}
};
};
Array.prototype.map = function (mapper) {
let gen = iter(this);
return {
[Symbol.iterator]: function () {
return {
next: () => {
let result = gen.next();
if (result.done) {
return result;
}
return {
value: mapper(result.value),
done: false
};
}
};
}
};
};
Array.prototype.toArray = function () {
let result = [];
for (let item of this) {
result.push(item);
}
return result;
};
// 取1到10中的偶数,然后取这些偶数的平方
var _1to10 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var arr = iter(_1to10)
.where(v => v % 2 === 0)
.map(v => v * v)
.toArray();
console.log(arr); // [4, 16, 36, 64, 100]
// 对年龄大于20的人,按年龄进行排序
var person = [
{ first: 'god', last: 'pig', age: 25, male: 'm' },
{ first: 'wang', last: 'er', age: 26, male: 'm' },
{ first: 'zhang', last: 'san', age: 18, male: 'm' },
{ first: 'li', last: 'si', age: 19, male: 'm' },
{ first: 'god', last: 'pig', age: 21, male: 'm' },
{ first: 'god', last: 'cat', age: 22, male: 'm' }
];
var arr = iter(person)
.where(v => v.age > 20)
.sort((v1, v2) => v1.age - v2.age)
.toArray();
console.log(arr); // [{..age:21..}, ..., {..age:26..}]
解释
- Generator 函数:
iter
函数是一个生成器函数,用于遍历数组。 - 链式方法:
where
方法用于过滤数组元素。map
方法用于转换数组元素。toArray
方法将生成器的结果转换为数组。
- 惰性求值:每个方法返回一个新的生成器对象,只有在调用
toArray
时才会实际执行操作。
这种方式使得代码更加简洁、可读性强,并且具有良好的扩展性。
这个问题讨论了如何使用ES6 Generator函数实现链式调用和惰性求值(lazy evaluation)来迭代数组。我们可以通过一个自定义的迭代器库iter
来实现类似的功能。
示例代码
function* iter(array) {
for (let item of array) {
yield item;
}
}
Array.prototype.where = function (predicate) {
return iter(this).filter(predicate);
};
Array.prototype.map = function (transform) {
return iter(this).map(transform);
};
Array.prototype.sort = function (comparator) {
return iter(this).sort(comparator);
};
Array.prototype.toArray = function () {
let result = [];
for (let item of this) {
result.push(item);
}
return result;
};
// 使用示例
var _1to10 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var arr = iter(_1to10)
.where(v => v % 2 === 0)
.map(v => v * v)
.toArray();
console.log(arr); // [4, 16, 36, 64, 100]
var person = [
{ first: 'god', last: 'pig', age: 25, male: 'm' },
{ first: 'wang', last: 'er', age: 26, male: 'm' },
{ first: 'zhang', last: 'san', age: 18, male: 'm' },
{ first: 'li', last: 'si', age: 19, male: 'm' },
{ first: 'god', last: 'pig', age: 21, male: 'm' },
{ first: 'god', last: 'cat', age: 22, male: 'm' }
];
var sortedPerson = iter(person)
.where(v => v.age > 20)
.sort((v1, v2) => v1.age - v2.age)
.toArray();
console.log(sortedPerson);
// [
// { first: 'god', last: 'pig', age: 21, male: 'm' },
// { first: 'god', last: 'cat', age: 22, male: 'm' },
// { first: 'god', last: 'pig', age: 25, male: 'm' },
// { first: 'wang', last: 'er', age: 26, male: 'm' }
// ]
解释
- Generator 函数:
iter
函数是一个生成器函数,用于逐个返回数组中的元素。 - 链式调用:通过在数组原型上添加方法(如
where
,map
,sort
,toArray
),我们可以实现链式调用,使得代码更加简洁。 - 惰性求值:由于使用了生成器,这些操作并不会立即执行,而是等到调用
toArray()
方法时才真正执行并收集结果。
这种方式的好处是延迟计算,只有在需要实际结果时才会触发所有的操作,从而提高了性能。