C# - 将参数作为输入的自定义 IComparer<T>

C# - custom IComparer<T> that takes an argument as input

我有一个点 (x,y) 列表,我想根据它们相对于参考点的极角对我计算为列表中所有点的平均点的参考点进行排序。 如何设置 IComparer 以便我可以将参考点传递给它以计算极角?

你有两个选择。

选项 A

参考点必须是您的 Point 对象的一部分。这样在你的Point的比较方法中,你可以考虑计算角度和比较对象。

public int IComparer.Compare(Point x, Point y)  {
  var angleX = Utilities.CalculateAngle(x.ReferencePoint);
  var angleY = Utilities.CalculateAngle(y.ReferencePoint);

  if (angleX < angleY) return -1;
  if (angleX == angleY) return 0;
  if (angleX > angleY) return 1;

  // Or simply "return angleX - angleY;"
}

选项 B

Angle 应该已经计算在你的点上了。使 Point 成为不可变结构,并在结构实例化时计算角度。那么就 OrderBy 那 属性.

public struct Point
{
  public double Angle { get; private set; }

  public Point(double referencePoint, double x, double y)
  {
    // TODO: Calculate Angle
  }
}

points.OrderBy(p => p.Angle);

你可以提前计算出参考点,传递给你IComparer的构造函数:

class PointComparer : IComparer<Point>
{
    private readonly Point referencePoint;

    public PointComparer(Point referencePoint)
    {
        this.referencePoint = referencePoint;
    }
    public Int32 Compare(Point x, Point y)
    {
        // Compare using referencePoint
    }
}

用法:

var ordered = myList.OrderBy(x => x, new PointComparer(calculatedReferencePoint));

我使用了 OrderyBy 而不是 Sort 因为当我们参考文档时后者被认为是不稳定的排序。