Zodiac - 6 months ago 49
C# Question

# C# LINQ - how to check if all elem satisfy condition

I have a list of object. Those objects contain lat and lon coordinates among other properties. I want to extract only thoose coordonates that satisfy

``````Math.Abs(elem1.lat - elem2.lat) < Delta && Math.Abs(elem1.lon - elem2.lon) < Delta
``````

Basically I want to extract only objects that dont have coordinates close to each other.

Is there an elegant way to do this with C# LINQ ?

EDIT :

So elem1 and elem2 are any 2 elements from the list. I want all elements that will result from the query to have more then delta between any of them

Your question is not well-phrased. If your `elem1` or `elem2` is a single item you want to compare against, this is pretty easy. Just do a LINQ `Where` to find the items that match the criteria.

``````Coordinates it = new Coordinates { lat = 5, lon = 5 };
var picked = list.Where(x => Math.Abs(x.lat - it.lat) < Delta && Math.Abs(x.lon - it.lon) < Delta);
``````

If, on the other hand, your two elements are any two elements in the list, then you run into a problem where you need to clarify things. As I mentioned in my comment, if your have `elem1`, `elem2`, and `elem3`, and if the first two don't match the criteria but if `elem2` and `elem3` do match the criteria, then are both of those elements (2 and 3) 'hits'? Assuming they are, the solution below will work. I wrote a simple Comparer to help make things easy as well.

``````public class CoordinateComparer : IEqualityComparer<Coordinates>
{
public bool Equals(Coordinates x, Coordinates y)
{
return (x.lat == y.lat && x.lon == y.lon);
}

public int GetHashCode(Coordinates obj)
{
unchecked
{
int hash = 17;
if (obj != null)
{
hash = hash * 23 + obj.lat.GetHashCode();
hash = hash * 23 + obj.lon.GetHashCode();
}
return hash;
}
}
}

public class Coordinates
{
public int lat { get; set; }
public int lon { get; set; }
}

class MainClass
{
public static void Main(string[] args)
{
List<Coordinates> list = new List<Coordinates>();
list.Add(new Coordinates { lat = 5, lon = 4 });
list.Add(new Coordinates { lat = 4, lon = 5 });
list.Add(new Coordinates { lat = 7, lon = 4 });
list.Add(new Coordinates { lat = 6, lon = 3 });
list.Add(new Coordinates { lat = 8, lon = 2 });

double Delta = 1.1;

List<Coordinates> results = new List<Coordinates>();
foreach(Coordinates item in list)
{
// Find items that match the condition
var matches = list.Where(x => Math.Abs(x.lat - item.lat) < Delta && Math.Abs(x.lon - item.lon) < Delta);
// The 'item' will always match the condition with itself, which is undesirable, so remove it
matches = matches.Except(new List<Coordinates> { item }, new CoordinateComparer());
// Add the items that are not already in it to the results list
Bear in mind that if your latitude and longitude coordinates are either `double` or `float`, which they probably are, you might run into problems when comparing. But that's an altogether different question.