Distinct not working with LINQ to Objects

后端 未结 9 1704
伪装坚强ぢ
伪装坚强ぢ 2020-11-22 12:20
class Program
{
    static void Main(string[] args)
    {
        List books = new List 
        {
            new Book
            {
                


        
相关标签:
9条回答
  • 2020-11-22 12:57

    You can use extension method on list which checks uniqueness based on computed Hash. You can also change extension method to support IEnumerable.

    Example:

    public class Employee{
    public string Name{get;set;}
    public int Age{get;set;}
    }
    
    List<Employee> employees = new List<Employee>();
    employees.Add(new Employee{Name="XYZ", Age=30});
    employees.Add(new Employee{Name="XYZ", Age=30});
    
    employees = employees.Unique(); //Gives list which contains unique objects. 
    

    Extension Method:

        public static class LinqExtension
            {
                public static List<T> Unique<T>(this List<T> input)
                {
                    HashSet<string> uniqueHashes = new HashSet<string>();
                    List<T> uniqueItems = new List<T>();
    
                    input.ForEach(x =>
                    {
                        string hashCode = ComputeHash(x);
    
                        if (uniqueHashes.Contains(hashCode))
                        {
                            return;
                        }
    
                        uniqueHashes.Add(hashCode);
                        uniqueItems.Add(x);
                    });
    
                    return uniqueItems;
                }
    
                private static string ComputeHash<T>(T entity)
                {
                    System.Security.Cryptography.SHA1CryptoServiceProvider sh = new System.Security.Cryptography.SHA1CryptoServiceProvider();
                    string input = JsonConvert.SerializeObject(entity);
    
                    byte[] originalBytes = ASCIIEncoding.Default.GetBytes(input);
                    byte[] encodedBytes = sh.ComputeHash(originalBytes);
    
                    return BitConverter.ToString(encodedBytes).Replace("-", "");
                }
    
    0 讨论(0)
  • 2020-11-22 12:58

    The Above answers are wrong!!! Distinct as stated on MSDN returns the default Equator which as stated The Default property checks whether type T implements the System.IEquatable interface and, if so, returns an EqualityComparer that uses that implementation. Otherwise, it returns an EqualityComparer that uses the overrides of Object.Equals and Object.GetHashCode provided by T

    Which means as long as you overide Equals you are fine.

    The reason you're code is not working is because you check firstname==lastname.

    see https://msdn.microsoft.com/library/bb348436(v=vs.100).aspx and https://msdn.microsoft.com/en-us/library/ms224763(v=vs.100).aspx

    0 讨论(0)
  • 2020-11-22 12:59

    Another solution without implementing IEquatable, Equals and GetHashCode is to use the LINQs GroupBy method and to select the first item from the IGrouping.

    var temp = books.SelectMany(book => book.Authors)
                    .GroupBy (y => y.FirstName + y.LastName )
                    .Select (y => y.First ());
    
    foreach (var author in temp){
      Console.WriteLine(author.FirstName + " " + author.LastName);
    }
    
    0 讨论(0)
提交回复
热议问题