доступ к предыдущему элементу в сгибе / уменьшении в дротике - PullRequest
2 голосов
/ 18 апреля 2020

Интересно, смогу ли я переписать этот кусок кода дротика:

 double length = 0;
 Point current = points.first;
 for (var next in points.skip(1)){
   length += current.distanceTo(next);
   current = next;
 }
 return length;

на что-то более сжатое и элегантное. Я думал об использовании Reduce / Fold, но есть ли способ получить доступ к прецедентному элементу итерируемой функции объединения?

Ответы [ 3 ]

3 голосов
/ 22 апреля 2020

Всегда есть альтернатива для l oop с повторяемостью.
Здесь реализовано logi c Фибоначчи и проверено быстродействие.

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

Результат: Здесь логика c, представленная с помощью для для l oop, занимает 2 микросекунды, в то время как Фибоначчи Logi c занимает всего 1.

1 голос
/ 27 апреля 2020

С функциональным стилем программирования и методами расширения дротиков:

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;
  }
}
0 голосов
/ 22 апреля 2020

Хорошо, это ответ, который я нашел - используя дополнительный объект (кажется, что он также немного быстрее):

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