2016-05-26 4 views
2

Существует список полигонов List<Polygon> Polygons, определенных этими классами.Заказать список списков в C#, используя LINQ

Как я могу заказать этот список, так что многоугольник упорядочен первым свойством их точки X, а затем с помощью Y свойства их точек в порядке возрастания.

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

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

Update: Для примера рассмотрим эти многоугольники:

(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) 

отсортированный выход:

(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) 
+2

http: // stackoverflow.com/questions/298725/multiple-order-by-in-linq –

+1

Что делать, если есть пересечения полигонов – user853710

+0

Спасибо @ user189756, но мой вопрос кажется немного иным, как я его понимаю. – Vahid

ответ

1

Вы, кажется, хотите заказать полигоны на основе наименьшего X значения их точки, и если они равны, то на основе наименьшего значения Y их точек.

Вот как вы можете сделать это с помощью 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(); 
+0

Я не думаю, что это то, что он делает, потому что иначе полигон B окажется раньше, чем полигон C (B и C - это имена в исходном списке, OP, похоже, не сохраняет их в отсортированном списке). Похоже, вы тоже это заметили (я имею в виду ваш комментарий к вопросу). – dasblinkenlight

+0

Кажется, это правильный ответ. Я сделал ошибку, готовя пример. Но вся идея правильная. – Vahid

+1

@dasblinkenlight, для Y, я изменил его с 'Min' на' Max', чтобы он работал для примера OP. Если ОП ошибается, он может изменить его обратно с «Макс» на «Мин». –

0

Что вам нужно, это первое индивидуального упорядочение каждых точек многоугольника на основе X и значений Y, то заказав каждый многоугольник сам по себе

Во-первых это сделать:

var polygonsWithOrderedPoints = 
    polygons.Select(points => points.OrderBy(p => p.X).ThenBy(p => p.Y).ToList()).ToList(); 

затем

var orderPolygons = polygonsWithOrderedPoints.OrderBy(p => p,PolygonComparer).ToList(); 

В этом случае каждый многоугольник имеет внутреннее упорядочение на основе точек X и Y соответственно. Теперь вы хотите, чтобы каждый Polygon объект в List<Polygon> быть дополнительно заказаны, для которого вам нужно IComparer<Polygon> на следующих линиях, который получает подается OrderBy для Polygon list

public class PolygonComparer : IComparer<Polygon> 
{  
    public int Compare(Polygon PolyA, Polygon PolyB) 
    { 
     var aPoints = PolyA.Points; 
     var bPoints = PolyB.Points; 

     for(int counter=0; counter < aPoints.Count;counter++) 
     { 
      Point2D a = aPoints[counter]; 
      Point2D b = aPoints[counter]; 

      int retVal = 0; 

      if(a.X == b.X && a.Y == b.Y) 
      continue; 
      else if(b.X > a.X) 
      retval = 1; 
      else if(a.Y > b.Y) 
      retval = 1 

     break; 
     } 
     return retval; 
    } 
} 
2

Вы должны добавить другие свойства к классу многоугольников

public class Polygon 
{ 
    public List<Point2D> Points; 

    public Point2D MinPoint; 
} 

Эта часть будет зависеть от того, как вы располагаете точками и апеллируете к подходящим вам алгоритмам. , тогда вам нужно найти точку минимума многоугольника. Один представитель многоугольника. Возможно, это центр, нижняя точка или центр выпуклого корпуса. Один представитель. (это может быть немного неправильно, но вам нужно немного поиграть с ним). Это зависит от различных сценариев

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

Тогда вы можете сортировать его.

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

вы также можете поместить часть минимальной точки в сам класс многоугольника – user853710

+1

Было бы также предложено реализовать в Point2D IComparable inteface, вы можете добавить сравнение двух точек непосредственно к методу и использовать стандартные механизмы сортировки. То же самое следует применять и к полигону. Это на самом деле решение «по книге» – user853710

+0

OrderBy нужен IComparer, а не IComparable –

0

Вы можете написать класс Comparer для сравнения точек внутри многоугольника и использовать, чтобы заказать многоугольники.

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()); 

Сторона примечания: вы можете захотеть превратить эти поля в свойства.

Смежные вопросы