eg

List<Student> StudentsGroup = new List<Student>(); StudentsGroup.add(new Student(){Name="Vasia", Surname="Andrienko"}); StudentsGroup.add(new Student(){Name="Vasia", Surname="Potapenko"}); StudentsGroup.add(new Student(){Name="Fedia", Surname="Matsenko"}); StudentsGroup.add(new Student(){Name="Kolia", Surname="Mischenknko"}); StudentsGroup.add(new Student(){Name="Vasilisa", Surname="Vynnychenko"}); StudentsGroup.add(new Student(){Name="Vasilisa", Surname="Onoprienko"}); 

after clearing by Name, it should give only the following data

 {Name="Vasia", Surname="Andrienko"}//иль второго студента {Name="Fedia", Surname="Matsenko"} {Name="Kolia", Surname="Mischenknko"} {Name="Vasilisa", Surname="Vynnychenko"}//иль второго студента 
  • 2
    put MoreLinq and call DistinctBy - vitidev
  • one
    @vitidev, to put a separate library in a project for what can be done with your 1m method - this is somehow a matter of some kind. Yes, I'd rather manually write the crooked method. :) - Andrew
  • one
    @vitidev, it is possible and normal Distinct, passing it IComparer - Grundy

4 answers 4

Without using third-party libraries

 StudentsGroup = StudentsGroup.GroupBy(x => x.Name).Select(x => x.First()).ToList(); 

Taken from an English SO

  • Thank you for what you need. Some edits and earned. Edit made here. - Andrew
  • @Andrew, removed ToList () - this should be used very selectively - Artem Flotsky
  • @Artem_Flotsky ToList () is needed there because The result of the select is IEnumerable and without it the result will not be assigned. Added back. :) - Andrew
  • @Andrew, with the assignment of yes, I agree. I would not like those who come here with the same question to perceive that ToList () should be used where possible =) - Artem Flotsky

Another option is to use Distinct overload, which takes the second parameter of IEqualityComparer<T>

For example:

 class StudentComparer : IEqualityComparer<Student> { // Students are equal if their names are equal. public bool Equals(Student x, Student y) { //Check whether the compared objects reference the same data. if (Object.ReferenceEquals(x, y)) return true; //Check whether any of the compared objects is null. if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false; //Check whether the Student's properties are equal. return x.Name == y.Name; } // If Equals() returns true for a pair of objects // then GetHashCode() must return the same value for these objects. public int GetHashCode(Student student) { //Check whether the object is null if (Object.ReferenceEquals(student, null)) return 0; //Get hash code for the Name field if it is not null. return student.Name == null ? 0 : student.Name.GetHashCode(); } } 

Example of use:

 IEnumerable<Student> noduplicates = StudentsGroup.Distinct(new StudentComparer()); 
  • Wouldn't it be easier to take a StringComparer or EqualityComparer<string>.Default and delegate directly the comparison to it? - Pavel Mayorov
  • @PavelMayorov, nea, in my opinion, this code is a compilation of msdn with a replaced type - Grundy
  • code inheritance is bad. Even if the code is inherited from msdn. - Pavel Mayorov
  • @PavelMayorov, by the way, how can I get StringComparer in here? Create an instance and call equals / gethashcode in it? But then just call x.Name == y.Name easier? rather, it will be replaced by the call equals = in my opinion not much big difference - Grundy
  • StringComparer implements IEqualityComparer<string> - Pavel Mayorov

You can take advantage of the Distinct method overload that takes an IEqualityComparer<T>

Instead of the full implementation of the IEqualityComparer<Student> you can delegate all the standard implementations, leaving you only to access the Name property:

 class StudentByNameComparer : IEqualityComparer<Student> { private readonly IEqualityComparer<string> cmp; public StudentByNameComparer(IEqualityComparer<string> cmp) { this.cmp = cmp; } public static StudentByNameComparer Default { get; } = new StudentByNameComparer(EqualityComparer<string>.Default); // Также тут можно использовать StringComparer public bool Equals(Student x, Student y) => cmp.Equals(x?.Name, y?.Name); public int GetHashCode(Student x) => cmp.GetHashCode(x?.Name); } 

Example of use:

 IEnumerable<Student> noduplicates = StudentsGroup.Distinct(StudentByNameComparer.Default); 
  • I won't get used to new opportunities :) - Grundy

If you form the collection, and the property to check is always the same, use HashSet for this purpose, and duplicates will not be added. Do not forget that it will be necessary to redefine GetHashCode to compose a hash only by a changing property.

 class Student { ... /// существующий код public override int GetHashCode() { unchecked { int hash = 13; // любое простое число return 13* Name.GetHashCode(); } } } 
  • Well, why multiply it by 13? - Qwertiy
  • This is another question that goes beyond the current one. In short, when hashing, not only multiplication is used, but also division along with logical operations. Simple numbers give less collisions, that's all. - Anton Shakalo
  • one
    This is a hint that in this case it is not necessary to do this;) Because there is no hash calculation based on several hashes, and the only field whose hash is returned has already been taken care of. Multiplying it by any number does not improve anything. - Qwertiy
  • Oh, so you would not start because of the stove) Yes, of course. But enlightenment is the same) - Anton Shakalo