使用 RxJava 减少自定义对象

Reduce custom object using RxJava

我正在使用 RxJava,我有一个点列表,我想计算每个点之间的距离并求和。

点class看起来像这样

public class Point {
    public double x;
    public double y;
}

所以我需要同时映射和减少,但我没有找到解决方案。

public Observable<Double> totalDistance(Observable<List<Point>> obs) {
 return obs.reduceMap(new ArrayList<Integer>, (list, pointA, pointB) -> distance(pointA, pointB)). ?
}

最有效的方法是什么(或者至少是有效的解决方案)?我应该使用哪个运算符?

举一个更具体的例子,这是我所拥有的和我想要的:

Point a (45, 32)
Point b (56, 75)
Point c (44, 53)
Point d (42, 54)
Point e (42, 55)

a to b = 10m
b to c = 15m
c to d = 25m
d to e = 10m

Result = 60m

实际上我的点是 GPS 位置,我使用 haversine 公式计算两个位置之间的距离。

我使用 observables 是因为要计算的点列表有时会更新。事实上,用户达到的每 x 个点,我都有一个指令要发送。发送指令后,一个新的点列表,直到发出下一条指令。

您可以尝试 buffer and reduce 运算符。例如:

public Observable<Double> totalDistance(Observable<List<Point>> obs) {
    return obs.flatMap(points ->
            Observable.fromIterable(points)
                    .buffer(2 /* count */, 1 /* skip */)
                    /* this emits a list of each two adjacent points from a given list of points. */
                    .reduce(0.0  /* initial value */, (totalDistance, twoPoints) -> {
                                // note: calculation may be skipped if the twoPoints list contains less than
                                // two elements.
                                final Point pointA = twoPoints.get(0);
                                final Point pointB = twoPoints.get(1);
                                return totalDistance + distance(pointA, pointB);
                            }
                    ).toObservable());
}

您可以使用 map() 方法将 Observable<List<Point>> 的值转换为 Observable<Double> 的值。代码可能如下所示:

public static void main(String[] args) throws Exception {
    Point a = new Point(45, 32);
    Point b = new Point(56, 75);
    Point c = new Point(44, 53);
    Point d = new Point(42, 54);
    Point e = new Point(42, 55);
    
    List<Point> points = new ArrayList<Point>();
    points.add(a);
    points.add(b);
    points.add(c);
    points.add(d);
    points.add(e);
    
    Subject<List<Point>> subjectOfListOfPoints = PublishSubject.create();
    
    Observable<List<Point>> observable = subjectOfListOfPoints;
    
    Observable<Double> doubleObservable = observable.map(it -> { 
        return calculateSumOfDistances(it); });
    
    doubleObservable.subscribe(it -> {
        System.out.println("The sum is: "+it);
    });
    
    subjectOfListOfPoints.onNext(points);
}

private static double calculateSumOfDistances(List<Point> points) {
    List<Double> distances = new ArrayList<Double>();
    for (int i=0; i<points.size()-1; i++) {
        double distance = distance(points.get(i), points.get(i+1));
        System.out.println("Distance is: "+distance);
        distances.add(distance);
    }
    double sum = 0;
    for (Double d: distances) {
        sum += d;
    }
    return sum;
}

private static double distance(Point a, Point b) {
    return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}

这将创建以下输出:

Distance is: 44.384682042344295
Distance is: 25.059928172283335
Distance is: 2.23606797749979
Distance is: 1.0
The sum is: 72.68067819212742