如何使用LINQ和C#找到最接近0,0点的点

本文关键字:0点 最接近 LINQ 何使用 | 更新日期: 2023-09-27 18:01:07

我有一个点列表(列表(

  • 7,43
  • 7,42
  • 6,42
  • 5,42
  • 6,43
  • 5,43

我想使用linq表达式来获得最接近0,0的点。例如,对于这个列表,我期望值为5,42。

如何使用LINQ找到最接近0,0点的点?

如何使用LINQ和C#找到最接近0,0点的点

以下查找具有最低L^2范数(二维中最常见的"距离"定义(的点,而不执行整个列表的昂贵排序:

var closestToOrigin = points
    .Select(p => new { Point = p, Distance2 = p.X * p.X + p.Y * p.Y })
    .Aggregate((p1, p2) => p1.Distance2 < p2.Distance2 ? p1 : p2)
    .Point;

试试这个:

List<Point> points = new List<Point>();
// populate list
var p = points.OrderBy(p => p.X * p.X + p.Y * p.Y).First();

或更快速的解决方案:

var p = points.Aggregate(
            (minPoint, next) =>
                 (minPoint.X * minPoint.X + minPoint.Y * minPoint.Y)
                 < (next.X * next.X + next.Y * next.Y) ? minPoint : next);

作为一种替代方法,您可以考虑在标准库中添加IEnumerable.MinBy((和IEnumerable.MaxBy(

如果你有可用的,代码就变成了:

var result = points.MinBy( p => p.X*p.X + p.Y*p.Y );

Jon Skeet提供了MinBy和MaxBy的良好实现。

他在这里谈到:如何使用LINQ来选择具有最小或最大属性值的对象

不过,那里的链接已经过时;最新版本在这里:

http://code.google.com/p/morelinq/source/browse/MoreLinq/MinBy.cs

http://code.google.com/p/morelinq/source/browse/MoreLinq/MaxBy.cs

这是一个完整的样品。很明显,这是一个破解难题的大锤,但我认为这些方法足够有用,可以包含在您的标准库中:

using System;
using System.Collections.Generic;
using System.Drawing;
namespace Demo
{
    public static class EnumerableExt
    {
        public static TSource MinBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IComparer<TKey> comparer)
        {
            using (IEnumerator<TSource> sourceIterator = source.GetEnumerator())
            {
                if (!sourceIterator.MoveNext())
                {
                    throw new InvalidOperationException("Sequence was empty");
                }
                TSource min = sourceIterator.Current;
                TKey minKey = selector(min);
                while (sourceIterator.MoveNext())
                {
                    TSource candidate = sourceIterator.Current;
                    TKey candidateProjected = selector(candidate);
                    if (comparer.Compare(candidateProjected, minKey) < 0)
                    {
                        min    = candidate;
                        minKey = candidateProjected;
                    }
                }
                return min;
            }
        }
        public static TSource MinBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
        {
            return source.MinBy(selector, Comparer<TKey>.Default);
        }
    }
    public static class Program
    {
        static void Main(string[] args)
        {
            List<Point> points = new List<Point>
            {
                new Point(7, 43),
                new Point(7, 42),
                new Point(6, 42),
                new Point(5, 42),
                new Point(6, 43),
                new Point(5, 43)
            };
            var result = points.MinBy( p => p.X*p.X + p.Y*p.Y );
            Console.WriteLine(result);
        }
    }
}

Rawling的解决方案肯定更短,但这里有一个替代

// project every element to get a map between it and the square of the distance
var map = pointsList                                            
    .Select(p => new { Point = p, Distance = p.x * p.x + p.y * p.y });
var closestPoint = map // get the list of points with the min distance
    .Where(m => m.Distance == map.Min(t => t.Distance)) 
    .First() // get the first item in that list (guaranteed to exist)
    .Point; // take the point

如果需要查找所有0,0距离最短的元素,只需删除First并执行Select(p => p.Point)即可获得点(与映射相反(。