As input I have a 2D array PointXY[][] clusters
, which looks like this:
[[23.237633,53.78671], [69.15293,17.138134], [23.558687,45.70517]] . . .
[[47
See another answer: Sorting a 2d array of objects by columns starting from the second row and transposing an array
Building sorted cluster. First row are the center points. Other points are grouped by the nearest center. In this case all points are grouped by the second center point:
PointXY[][] clusters = {
{new PointXY(23.237633, 53.78671),
new PointXY(69.15293, 17.138134),
new PointXY(23.558687, 45.70517)},
{new PointXY(47.851738, 16.525734),
new PointXY(47.802097, 16.689285),
new PointXY(47.946404, 16.732542)},
{new PointXY(47.89601, 16.638218),
new PointXY(47.833263, 16.478987),
new PointXY(47.88203, 16.45793)},
{new PointXY(47.75438, 16.549816),
new PointXY(47.915512, 16.506475),
new PointXY(47.768547, 16.67624)}};
// array of a center points
PointXY[] centers = clusters[0];
PointXY[][] clustersSorted = Arrays
// iterate over array of center points
.stream(centers)
// for each center point
.map(center -> Stream.of(center, Arrays
// iterate over array of clusters starting from the second row
.stream(clusters, 1, clusters.length)
// stream over the full array
.flatMap(Arrays::stream)
// filter nearest points to the current center point
.filter(point -> Arrays
// iterate over array of center points
.stream(centers)
// sort by euclidean distance from current point
.sorted(Comparator.comparingDouble(centerXY ->
Math.sqrt(Math.pow(centerXY.x - point.x, 2)
+ Math.pow(centerXY.y - point.y, 2))))
// find nearest center point to the current point
.findFirst()
// check this center point is the current center point
.get() == center)
// array of the nearest points to this center point
.toArray(PointXY[]::new))
// center point + array of its nearest points
.flatMap(element -> element instanceof PointXY ?
Stream.of((PointXY) element) :
Arrays.stream((PointXY[]) element))
// sorted cluster
.toArray(PointXY[]::new))
// sorted array of clusters
.toArray(PointXY[][]::new);
// output
Arrays.stream(clustersSorted).map(Arrays::toString).forEach(System.out::println);
[23.237633,53.78671]
[69.15293,17.138134, 47.851738,16.525734, 47.802097,16.689285, 47.946404,16.732542, 47.89601,16.638218, 47.833263,16.478987, 47.88203,16.45793, 47.75438,16.549816, 47.915512,16.506475, 47.768547,16.67624]
[23.558687,45.70517]
Class PointXY
should look like this:
public static class PointXY {
double x, y;
public PointXY(double x, double y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return x + "," + y;
}
}