Vahid
Vahid

Reputation: 5454

Order a list of lists in C# using LINQ

There is a list of polygons List<Polygon> Polygons defined by these classes.

How can I order that list, so that the polygon are ordered first by the X property of their Points and then by the Y property of their Points in an ascending order.

public class Polygon
{
    public List<Point2D> Points;
}

public class Point2D
{
    public double X;
    public double Y;
}

Update: For example consider these polygons:

(A) (0, 0) -> (5, 1) -> (5, -3) -> (0, -3) -> (0, 0)
(B) (0, -10) -> (5, -9) -> (5, -13) -> (0, -13) -> (0, -10)
(C) (10, 0) -> (15, 1) -> (15, -3) -> (10, -3) -> (10, 0)

the sorted output:

(A) (0, -10) -> (5, -9) -> (5, -13) -> (0, -13) -> (0, -10)
(B) (0, 0) -> (5, 1) -> (5, -3) -> (0, -3) -> (0, 0)
(C) (10, 0) -> (15, 1) -> (15, -3) -> (10, -3) -> (10, 0)

Upvotes: 2

Views: 394

Answers (3)

user853710
user853710

Reputation: 1767

You need to add other properties to the polygon class

public class Polygon
{
    public List<Point2D> Points;

    public Point2D MinPoint;
}

This part will depend on the distibution of you points and adept the algorith fitting to you needs. then you need to find the min point of a polygon One representative of the polygon. Might be the center, bottomleft point or center of a convex hull. One representative. (this might be a bit wrong but you need to play with it a bit). This depend on the various scenarios

foreach(var poly in Polygons)
{
    int minx = poly.Points.Min(p=>p.X);
    int minY = poly.Points.Where(p=>p.X==minX).Min(p=>p.Y);
    poly.MinPoint = poly.Points.FirstOrDefault(p=>p.X==minX && p.Y==minY)
}

Then you can sort it.

var sortedPolygons = polygons.OrderBy(p=>p.MinPoint.X).ThenBy(p=>p.MinPoint.Y);

Upvotes: 2

Yacoub Massad
Yacoub Massad

Reputation: 27871

You seem to want to order the polygons based on the smallest X value of their points, and if these are equal, then based on the smallest Y value of their points.

Here is how you can do it with LINQ:

var result =
    Polygons
    //Order by smallest X
    .OrderBy(pl => pl.Points.Min(pn => pn.X)) 
    //Then by smallest Y
    .ThenBy(pl => pl.Points.Min(pn => pn.Y))
    .ToList();

Upvotes: 1

Dennis_E
Dennis_E

Reputation: 8904

You can write a Comparer class for comparing the Points inside a polygon and use that to order the polygons.

class PointsComparer : IComparer<List<Point2D>>
{
    public int Compare(List<Point2D> left, List<Point2D> right)
    {
        for (int i = 0; i < left.Count && i < right.Count; i++) {
            int c = left[i].X.CompareTo(right[i].X);
            if (c != 0) return c;
            c = left[i].Y.CompareTo(right[i].Y);
            if (c != 0) return c;
        }
        return left.Count.CompareTo(right.Count);
    }
}


polygons.OrderBy(poly => poly.Points, new PointsComparer());

Side note: you may want to turn those fields into properties.

Upvotes: 0

Related Questions