在环顾StackOverflow时,我发现了一些按一个属性排序列表的例子,或者点之间的距离排序,但没有斜率排序。我对C#不是很熟悉,也很乐意帮忙。
我有一个点列表: (1,1)(2,5)(3,3)(7,1)
这看起来像这样:
--x-----
--------
---x----
--------
-x-----x
--------
我想计算从最左边的点(1,1)到另一个点的斜率:
然后按降序对它们进行排序。
斜率由y中的增益除以x中的增益("运行中的上升")确定。
斜坡会产生以下结果:
如何使用C#执行此操作?
我已经能够做到这一点:numbers.OrderBy(p => p.X);
并且我认为解决方案应该是这样的:
Point anchorPoint = new Point(1,1);
numbers = numbers.OrderBy(p => (p.Y - anchorPoint.Y)/(p.X - anchorPoint.X));
但是还没有能够解决这个问题。
答案 0 :(得分:1)
你很接近 - 你只需要将“锚点”作为列表中的第一个点,并在前面放置任何“无限”斜坡:
Point anchorPoint = numbers[0];
var query =
numbers.Select((p,i) => new {p,i}) // to get the index of each point
.OrderBy(pi => pi.i == 0 ? 0 : 1) // keep the first point first
.ThenByDescending(pi => (pi.p.X == anchorPoint.X) ? double.PositiveInfinity
: (pi.p.Y * 1.0 - anchorPoint.Y)/(pi.p.X - anchorPoint.X)) // infinite slopes first, the finite slopes descending
.Select(pi => p);
请注意,我将其中一个值乘以1.0,以将整数 divison转换为浮点除法。
您也可以“跳过”第一个点,订购其余点,然后连接结果:
var query =
numbers.Take(1).Concat(
numbers.Skip(1)
.OrderByDescending(p => (p.X == anchorPoint.X) ? double.PositiveInfinity
: (p.Y * 1.0 - anchorPoint.Y)/(p.X - anchorPoint.X))
);
这有点干净,因为您没有对匿名类型的投影来包含索引。
答案 1 :(得分:0)
感谢所有出色的答案。
我弄清楚了我的错误:打字。
我试图将我的排序结果返回到我订购的列表中。 List和OrderedList之间存在脱节。为了解决这个问题,我添加了.ToList()
来电。
numbers = numbers.OrderBy(p => (p.Y - anchorPoint.Y)/(p.X - anchorPoint.X)).ToList();