Removing duplicates from an array of strings

I'm new to C #, looked at numerous posts, but I'm still confused.

I have a list of arrays:

List<Array> moves = new List<Array>(); 

I add moves to it using the following:

 string[] newmove = { piece, axis.ToString(), direction.ToString() }; moves.Add(newmove); 

And now I want to remove duplicates using the following:

 moves = moves.Distinct(); 

However, this does not allow me to do this. I get this error:

It is not possible to implicitly convert the type 'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.List'. Explicit conversion exists (are you skipping listing?)

Help me please? I would be so grateful.

Steve

+4
source share
4 answers

There are two errors in your code. The first is the missing ToList call, as already mentioned. The second is thin. Unique compares objects by identifier, but your duplicate list items have different array instances.

There are several solutions to this problem.

  • Use your own comparisons moves.Distinct().ToList() in moves.Distinct().ToList() . No further changes are required.

    Implementation Example:

     class ArrayEqualityComparer<T> : EqualityComparer<T> { public override bool Equals(T[] x, T[] y) { if ( x == null ) return y == null; else if ( y == null ) return false; return x.SequenceEquals(y); } public override int GetHashCode(T[] obj) { if ( obj == null) return 0; return obj.Aggregate(0, (hash, x) => hash ^ x.GetHashCode()); } } 

    Filtering unique items:

     moves = moves.Distinct(new ArrayEqualityComparer<string>()).ToList(); 
  • Use Tuple <string,string,string> instead of string[] . Tuple offers built-in structural equality and comparison. This option may make your code cluttered due to the long type name.

    Instantiation:

     List<Tuple<string, string, string>> moves = new List<Tuple<string, string, string>>(); 

    Adding new moves:

     Tuple<string, string, string> newmove = Tuple.Create(piece, axis.ToString(), direction.ToString()); moves.Add(newmove); 

    Filtering unique items:

     moves = moves.Distinct().ToList(); 
  • Use your own class to store three values. I would recommend this option because it makes all of your movement codes more readable.

    Implementation Example:

     class Move { public Move(string piece, string axis, string direction) { Piece = piece; Axis = axis; Direction = direction; } string Piece { get; private set; } string Axis { get; private set; } string Direction { get; private set; } public override Equals(object obj) { Move other = obj as Move; if ( other != null ) return Piece == other.Piece && Axis == other.Axis && Direction == other.Direction; return false; } public override GetHashCode() { return Piece.GetHashCode() ^ Axis.GetHashCode() ^ Direction.GetHashCode(); } // TODO: override ToString() as well } 

    Instantiation:

     List<Move> moves = new List<Move>(); 

    Adding new moves:

     Move newmove = new Move(piece, axis.ToString(), direction.ToString()); moves.Add(newmove); 

    Filtering unique items:

     moves = moves.Distinct().ToList(); 
+3
source

You need to call .ToList() after the .Distinct method, as it returns an IEnumerable<T> . I would also recommend using a strongly typed List<string[]> instead of List<Array> :

 List<string[]> moves = new List<string[]>(); string[] newmove = { piece, axis.ToString(), direction.ToString() }; moves.Add(newmove); moves.Add(newmove); moves = moves.Distinct().ToList(); // At this stage moves.Count = 1 
+3
source

The compiler error is that you need to convert the result to a list:

 moves = moves.Distinct().ToList(); 

However, it probably will not work the way you want, because the arrays do not have Equals defined as you expect (it compares the references of the objects of the array, not the values ​​inside the array). Instead of using an array, create a class to hold your data and define Equals and GetHashCode to compare values.

+2
source

Old question, but this is O (n) solution using O (1) extra space:

 public static void RemoveDuplicates(string[] array) { int c = 0; int i = -1; for (int n = 1; n < array.Length; n++) { if (array[c] == array[n]) { if (i == -1) { i = n; } } else { if (i == -1) { c++; } else { array[i] = array[n]; c++; i++; } } } } 
0
source

All Articles