I have a list of points (List)
- 7,43
- 7,42
- 6,42
- 5,42
- 6,43
- 5,43
I want to use linq expression to get the point closest to 0,0. For example - for this list I expect 5,42 value.
How to find point closest to 0,0 point with LINQ?
I have a list of points (List)
I want to use linq expression to get the point closest to 0,0. For example - for this list I expect 5,42 value.
How to find point closest to 0,0 point with LINQ?
The following finds the point with the lowest L^2
norm (most common definition of "distance" in two dimensions) without performing an expensive sort of the whole list:
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;
Try this:
List<Point> points = new List<Point>();
// populate list
var p = points.OrderBy(p => p.X * p.X + p.Y * p.Y).First();
or more fast solution:
var p = points.Aggregate(
(minPoint, next) =>
(minPoint.X * minPoint.X + minPoint.Y * minPoint.Y)
< (next.X * next.X + next.Y * next.Y) ? minPoint : next);
Rawling's solution is definitely shorter, but here's an alternative
// 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
In case you need to find all the elements that have the shortest distance to 0,0
, simply remove First
and do a Select(p => p.Point)
to get the points (as opposed to the mapping).
As an alternative approach, you might consider adding to your standard libraries an implementation of IEnumerable.MinBy() and IEnumerable.MaxBy().
If you have that available, the code becomes simply:
var result = points.MinBy( p => p.X*p.X + p.Y*p.Y );
Jon Skeet has provided a good implementation of MinBy and MaxBy.
He talks about it here: How to use LINQ to select object with minimum or maximum property value
The links from there are out of date though; the latest version is here:
http://code.google.com/p/morelinq/source/browse/MoreLinq/MinBy.cs
http://code.google.com/p/morelinq/source/browse/MoreLinq/MaxBy.cs
Here's a full sample. Clearly, this is a sledgehammer to crack a nut, BUT I think these methods are useful enough to include in your standard libraries:
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);
}
}
}