I have a List of custom a datatype, simplified example (myMovies
):
public class Movie
{
public Int32 TVIndex;
public string MovieName;
public string MovieRating;
public string MovieRuntime;
public List<Actor> MovieActors;
public List<MovieArt> MovieImages;
}
public class Actor
{
public string ActorName;
public string ActorRole;
}
public class MovieArt
{
public string ImagePath;
}
List<Movie> myMovies = new List<Movie>();
Now I am trying to remove all duplicates from myMovies
but ignoring TVIndex
.
I have tried looking at
List<Movie> myDistinctMovies = myMovies.Distinct().ToList();
But cannot figure out how to ignore TvIndex
. Is this possible?
C# Linq Distinct() method removes the duplicate elements from a sequence (list) and returns the distinct elements from a single data source. It comes under the Set operators' category in LINQ query operators, and the method works the same way as the DISTINCT directive in Structured Query Language (SQL).
To get unique elements. List<int> myList = list. Distinct(). ToList();
distinct in Linq to get result based on one field of the table (so do not require a whole duplicated records from table). I know writing basic query using distinct as followed: var query = (from r in table1 orderby r. Text select r).
LINQ Distinct operator removes all the duplicate values from the collection and finally returns the dissimilar or unique values. The LINQ Distinct operator available in only Method Syntax and it not supports the Query Syntax. LINQ Distinct is an operator which comes under Set Operator.
Based on @Grundy's answer, including implementation:
public class MovieEqualityComparer : IEqualityComparer<Movie>
{
public bool Equals(Movie x, Movie y)
{
if ( x == null )
return y == null;
if ( y == null )
return x == null;
if ( object.ReferenceEquals(x, y) )
return true;
if ( !string.Equals(x.MovieName, y.MovieName) )
return false;
if ( !string.Equals(x.MovieRating, y.MovieRating) )
return false;
if ( !string.Equals(x.MovieRuntime, y.MovieRuntime) )
return false;
if ( !Enumerable.SequenceEqual(x.MovieActors, y.MovieActors) )
return false;
if ( !Enumerable.SequenceEqual(x.MovieImages, y.MovieImages) )
return false;
return true;
}
public int GetHashCode(Movie obj)
{
if ( obj == null )
throw new ArgumentNullException();
unchecked
{
int hash = 17;
hash = hash * 31 + ((obj.MovieName == null) ? 0 : obj.MovieName.GetHashCode());
hash = hash * 31 + ((obj.MovieRating == null) ? 0 : obj.MovieRating.GetHashCode());
hash = hash * 31 + ((obj.MovieRuntime == null) ? 0 : obj.MovieRuntime.GetHashCode());
if ( obj.MovieActors != null )
{
foreach ( var actor in obj.MovieActors )
hash = hash * 31 + ((actor == null) ? 0 : actor.GetHashCode());
}
if ( obj.MovieImages != null )
{
foreach ( var image in obj.MovieImages )
hash = hash * 31 + ((image == null) ? 0 : image.GetHashCode());
}
return hash;
}
}
}
Usage is the same:
List<Movie> myMovies = new List<Movie>
{
// ...
};
List<Movie> myDistinctMovies = myMovies.Distinct(new MovieEqualityComparer()).ToList();
EDIT
As pointed out by @Tim, you have to do something quite similar for your other custom types if you want to compare by anything other than reference equality.
public class Actor : IEquatable<Actor>
{
public string ActorName;
public string ActorRole;
public override bool Equals(object obj)
{
return this.Equals(obj as Actor);
}
public bool Equals(Actor other)
{
if ( other == null )
return false;
if ( object.ReferenceEquals(this, other) )
return true;
if ( !string.Equals(this.ActorName, other.ActorName) )
return false;
if ( !string.Equals(this.ActorRole, other.ActorRole) )
return false;
return true;
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 31 + ((ActorName == null) ? 0 : ActorName.GetHashCode());
hash = hash * 31 + ((ActorRole == null) ? 0 : ActorRole.GetHashCode());
return hash;
}
}
}
public class MovieArt : IEquatable<MovieArt>
{
public string ImagePath;
public override bool Equals(object obj)
{
return this.Equals(obj as MovieArt);
}
public bool Equals(MovieArt other)
{
if ( other == null )
return false;
if ( object.ReferenceEquals(this, other) )
return true;
if ( !string.Equals(this.ImagePath, other.ImagePath) )
return false;
return true;
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 31 + ((ImagePath == null) ? 0 : ImagePath.GetHashCode());
return hash;
}
}
}
you can use Distinct with EqualityComparer something like this
public class MoviesEqualityComparer : IEqualityComparer<Movie>
{
public bool Equals(Movie x, Movie y)
{
return ..../* check all needed fields */
}
public int GetHashCode(Movie obj)
{
return .... /* get hashcode for movie objec*/
}
}
and use it like
List<Movie> myDistinctMovies = myMovies.Distinct(new MoviesEqualityComparer()).ToList();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With