Ibrahem Hamdy Naeem Ibrahem Hamdy Naeem - 3 months ago 21
C# Question

Remove duplicates in a list of XYZ points

Mylist.GroupBy(x => new{x.X, x.Y}).Select(g => g.First()).ToList<XYZ>();


The above code works fine with me. I only want to compare the points based on the round(5) of the point component.

For example
x.X = 16.838974347323224
, I would it to compare only
x.X = 16.83897
cause I experienced some inaccuracy after the round 5. Any suggestions?

Update :
solved by implementing

Mylist.GroupBy(x => new { X = Math.Round(x.X,5), Y = Math.Round(x.Y,5) })
.Select(g => g.First()).ToList();

Answer

To do so use Math.Round:

var result = Mylist.GroupBy(x => new { X = Math.Round(x.X,5, MidpointRounding.AwayFromZero), Y = Math.Round(x.Y,5, MidpointRounding.AwayFromZero) })
                   .Select(g => g.First()).ToList();

However if what you want is to remove duplicates then instead of GroupBy go for one of these:

  1. Select rounded and then Distinct:

    var result = Mylist.Select(item => new XYZ { X = Math.Round(item.X,5, MidpointRounding.AwayFromZero), 
                                                 Y = Math.Round(item.Y,5, MidpointRounding.AwayFromZero)})
                       .Distinct().ToList();
    
  2. Distinct and override Equals and GetHashCode - (equals will do the rounding) - wouldn't suggest

  3. Distinct and implement a custom IEqualityComparer:

    public class RoundedXyzComparer : IEqualityComparer<XYZ>
    {
        public int RoundingDigits { get; set; }
        public RoundedXyzComparer(int roundingDigits)
        {
           RoundingDigits = roundingDigits;
        }
    
        public bool Equals(XYZ x, XYZ y)
        {
           return Math.Round(x.X, RoundingDigits, MidpointRounding.AwayFromZero) == Math.Round(y.X, RoundingDigits, MidpointRounding.AwayFromZero) && 
                  Math.Round(x.Y,RoundingDigits, MidpointRounding.AwayFromZero) == Math.Round(y.Y, RoundingDigits, MidpointRounding.AwayFromZero);
        }
    
        public int GetHashCode(XYZ obj)
        {
           return Math.Round(obj.X, RoundingDigits, MidpointRounding.AwayFromZero).GetHashCode() ^
                  Math.Round(obj.Y, RoundingDigits, MidpointRounding.AwayFromZero).GetHashCode();
        }
     }
    
     //Use:
     myList.Distinct(new RoundedXyzComparer(5));