在飞镖中访问 fold/reduce 中的上一个元素
accessing previous element in fold/reduce in dart
不知能否重写这段dart代码:
double length = 0;
Point current = points.first;
for (var next in points.skip(1)){
length += current.distanceTo(next);
current = next;
}
return length;
更简洁优雅的东西。我正在考虑使用 reduce / fold,但是有没有办法在组合函数中访问可迭代的先例元素?
总有一种方法可以替代带有可迭代的 for 循环。
在这里实现了斐波那契逻辑并检查了性能。
import 'dart:math';
double fibSum = 0;
double quesSum = 0;
List<Point> listOfPoints = [Point(0, 0), Point(1, 1), Point(1, 4)];
void main() {
print("before fibonacciLogic: ${DateTime.now()}");
fibonacciLogic(listOfPoints.length);
print("after fibonacciLogic: ${DateTime.now()}");
print("before logicFromQuestion(): ${DateTime.now()}");
logicFromQuestion();
print("after logicFromQuestion(): ${DateTime.now()}");
print("output fibonacciLogic: $fibSum");
print("output logicFromQuestion: $quesSum");
}
fibonacciLogic(int length) {
if (length < 2) {
return length;
}
fibSum += listOfPoints
.elementAt(length - 2)
.distanceTo(listOfPoints.elementAt(length - 1));
return fibonacciLogic(length - 2) + fibonacciLogic(length - 1);
}
logicFromQuestion() {
Point current = listOfPoints.first;
for (var next in listOfPoints.skip(1)) {
quesSum += current.distanceTo(next);
current = next;
}
return quesSum;
}
输出:
before fibonacciLogic: 2020-04-22 14:39:37.170
after fibonacciLogic: 2020-04-22 14:39:37.172
before logicFromQuestion(): 2020-04-22 14:39:37.172
after logicFromQuestion(): 2020-04-22 14:39:37.173
output fibonacciLogic: 4.414213562373095
output logicFromQuestion: 4.414213562373095
结果:
这里有问题的 for 循环逻辑需要 2 微秒,而斐波那契逻辑只需要 1.
好吧,这是我找到的答案——使用额外的对象(它似乎也稍微快一点):
class Point {
int x;
Point(this.x);
int distanceTo(Point p) {
return p == null ? 0 : (x - p.x).abs();
}
}
class PointAccumulator {
Point current;
int length = 0;
PointAccumulator(this.current);
}
void main() {
List<Point> points = [Point(1), Point(10), Point(20)];
int loops = 1000000;
int length = 0;
Stopwatch s = Stopwatch();
s.start();
for (var i = 0; i < loops; i++) {
// Standard method
length = 0;
Point current = points.first;
for (var next in points.skip(1)) {
length += current.distanceTo(next);
current = next;
}
}
s.stop();
print(s.elapsed);
print(length);
PointAccumulator pa;
s = Stopwatch();
s.start();
for (var i = 0; i < loops; i++) {
// with extra object
pa = points.fold(PointAccumulator(points.first),
(PointAccumulator pa, Point next) {
pa.length += next.distanceTo(pa.current);
pa.current = next;
return pa;
});
}
s.stop();
print(s.elapsed);
print(pa.length);
}
具有函数式编程风格和 dart 扩展方法:
extension MyExtensions<T> on Iterable<T> {
T foldByPairs(T initialValue, T combine(T value, T previous, T current)) {
Iterator<T> iterator = this.iterator;
iterator.moveNext(); // error handling omitted for brevity
T value = initialValue;
T previous = iterator.current;
while (iterator.moveNext()) {
T current = iterator.current;
value = combine(value, previous, current);
previous = current;
}
return value;
}
}
不知能否重写这段dart代码:
double length = 0;
Point current = points.first;
for (var next in points.skip(1)){
length += current.distanceTo(next);
current = next;
}
return length;
更简洁优雅的东西。我正在考虑使用 reduce / fold,但是有没有办法在组合函数中访问可迭代的先例元素?
总有一种方法可以替代带有可迭代的 for 循环。
在这里实现了斐波那契逻辑并检查了性能。
import 'dart:math';
double fibSum = 0;
double quesSum = 0;
List<Point> listOfPoints = [Point(0, 0), Point(1, 1), Point(1, 4)];
void main() {
print("before fibonacciLogic: ${DateTime.now()}");
fibonacciLogic(listOfPoints.length);
print("after fibonacciLogic: ${DateTime.now()}");
print("before logicFromQuestion(): ${DateTime.now()}");
logicFromQuestion();
print("after logicFromQuestion(): ${DateTime.now()}");
print("output fibonacciLogic: $fibSum");
print("output logicFromQuestion: $quesSum");
}
fibonacciLogic(int length) {
if (length < 2) {
return length;
}
fibSum += listOfPoints
.elementAt(length - 2)
.distanceTo(listOfPoints.elementAt(length - 1));
return fibonacciLogic(length - 2) + fibonacciLogic(length - 1);
}
logicFromQuestion() {
Point current = listOfPoints.first;
for (var next in listOfPoints.skip(1)) {
quesSum += current.distanceTo(next);
current = next;
}
return quesSum;
}
输出:
before fibonacciLogic: 2020-04-22 14:39:37.170
after fibonacciLogic: 2020-04-22 14:39:37.172
before logicFromQuestion(): 2020-04-22 14:39:37.172
after logicFromQuestion(): 2020-04-22 14:39:37.173
output fibonacciLogic: 4.414213562373095
output logicFromQuestion: 4.414213562373095
结果: 这里有问题的 for 循环逻辑需要 2 微秒,而斐波那契逻辑只需要 1.
好吧,这是我找到的答案——使用额外的对象(它似乎也稍微快一点):
class Point {
int x;
Point(this.x);
int distanceTo(Point p) {
return p == null ? 0 : (x - p.x).abs();
}
}
class PointAccumulator {
Point current;
int length = 0;
PointAccumulator(this.current);
}
void main() {
List<Point> points = [Point(1), Point(10), Point(20)];
int loops = 1000000;
int length = 0;
Stopwatch s = Stopwatch();
s.start();
for (var i = 0; i < loops; i++) {
// Standard method
length = 0;
Point current = points.first;
for (var next in points.skip(1)) {
length += current.distanceTo(next);
current = next;
}
}
s.stop();
print(s.elapsed);
print(length);
PointAccumulator pa;
s = Stopwatch();
s.start();
for (var i = 0; i < loops; i++) {
// with extra object
pa = points.fold(PointAccumulator(points.first),
(PointAccumulator pa, Point next) {
pa.length += next.distanceTo(pa.current);
pa.current = next;
return pa;
});
}
s.stop();
print(s.elapsed);
print(pa.length);
}
具有函数式编程风格和 dart 扩展方法:
extension MyExtensions<T> on Iterable<T> {
T foldByPairs(T initialValue, T combine(T value, T previous, T current)) {
Iterator<T> iterator = this.iterator;
iterator.moveNext(); // error handling omitted for brevity
T value = initialValue;
T previous = iterator.current;
while (iterator.moveNext()) {
T current = iterator.current;
value = combine(value, previous, current);
previous = current;
}
return value;
}
}