gpt4 book ai didi

javascript - 链接 map reduce 过滤器时如何减少迭代?

转载 作者:行者123 更新时间:2023-11-29 16:38:19 24 4
gpt4 key购买 nike

我一直在阅读有关 mapreducefilter 的文章,因为它们通常在 React 和 FP 中使用了很多。如果我们这样写:

let myArr = [1,2,3,4,5,6,7,8,9]
let sumOfDoubleOfOddNumbers = myArr.filter(num => num % 2)
.map(num => num * 2)
.reduce((acc, currVal) => acc + currVal, 0);

运行了 3 个不同的循环。

我也读过有关 Java 8 流的信息,并且知道它们使用所谓的 monad,即首先存储计算。它们在一次迭代中只执行一次。例如,

Stream.of("d2", "a2", "b1", "b3", "c")
.map(s -> {
System.out.println("map: " + s);
return s.toUpperCase();
})
.filter(s -> {
System.out.println("filter: " + s);
return s.startsWith("A");
})
.forEach(s -> System.out.println("forEach: " + s));

// map: d2
// filter: D2
// map: a2
// filter: A2
// forEach: A2
// map: b1
// filter: B1
// map: b3
// filter: B3
// map: c
// filter: C

PS:Java代码取自:http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/

还有许多其他语言使用相同的方法。有没有办法在 JS 中也以同样的方式做到这一点?

最佳答案

这是您的 Java 代码的精确克隆。与 Bergi 的解决方案不同,无需修改全局原型(prototype)。

class Stream {
constructor(iter) {
this.iter = iter;
}

* [Symbol.iterator]() {
yield* this.iter;
}

static of(...args) {
return new this(function* () {
yield* args
}());
}

_chain(next) {
return new this.constructor(next.call(this));
}

map(fn) {
return this._chain(function* () {
for (let a of this)
yield fn(a);
});
}

filter(fn) {
return this._chain(function* () {
for (let a of this)
if (fn(a))
yield (a);
});
}

forEach(fn) {
for (let a of this)
fn(a)
}
}


Stream.of("d2", "a2", "b1", "b3", "c")
.map(s => {
console.log("map: " + s);
return s.toUpperCase();
})
.filter(s => {
console.log("filter: " + s);
return s.startsWith("A");
})
.forEach(s => console.log('forEach', s));

实际上,链接功能可以从特定的迭代器中解耦以提供通用框架:

// polyfill, remove me later on
Array.prototype.values = Array.prototype.values || function* () { yield* this };

class Iter {
constructor(iter) { this.iter = iter }
* [Symbol.iterator]() { yield* this.iter }
static of(...args) { return this.from(args) }
static from(args) { return new this(args.values()) }
_(gen) { return new this.constructor(gen.call(this)) }
}

现在,您可以将任意生成器放入其中,包括预定义生成器和临时生成器,例如:

let map = fn => function* () {
for (let a of this)
yield fn(a);
};

let filter = fn => function* () {
for (let a of this)
if (fn(a))
yield (a);
};

it = Iter.of("d2", "a2", "b1", "b3", "c", "a000")
._(map(s => s.toUpperCase()))
._(filter(s => s.startsWith("A")))
._(function*() {
for (let x of [...this].sort())
yield x;
});

console.log([...it])

关于javascript - 链接 map reduce 过滤器时如何减少迭代?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49221528/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com