从字符串数组中删除重复项

4

我是C#的初学者,看了很多帖子但仍然感到困惑。

我有一个数组列表:

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

我正在使用以下方法为其添加动作:

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

现在我想使用以下方法去除重复项:

moves = moves.Distinct();

然而我无法这样做。我收到了以下错误:

无法隐式将类型 'System.Collections.Generic.IEnumerable' 转换为 'System.Collections.Generic.List'。存在显式转换(是否缺少强制转换?)

请帮帮我好吗?非常感谢。

Steve

4个回答

4

在调用.Distinct方法后,你需要使用.ToList()方法,因为它返回的是IEnumerable<T>类型。我还建议你使用强类型的List<string[]>而不是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

谢谢,已更改为强类型的List<string[]>。不幸的是,它根本没有删除重复项,尽管我不再收到错误消息。 - Steve Gore
1
@Steve G,也许是因为没有重复项?当我使用硬编码值测试此代码并插入两次相同的数组时,Distinct方法会删除重复项。 - Darin Dimitrov

3

你的代码有两个错误。第一个错误是缺少对ToList的调用,这已经被指出。第二个错误比较微妙。Unique通过对象的标识进行比较,但是你的重复列表项具有不同的数组实例。

有多种解决方法可以解决这个问题。

  • Use a custom equality comparer in moves.Distinct().ToList(). No further changes necessary.

    Sample implementation:

    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 for 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 variant might make your code cluttered because of 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 for unique items:

    moves = moves.Distinct().ToList();
    
  • Use a custom class to hold your three values. I'd actually recommend this variant, because it makes all your code dealing with moves much more readable.

    Sample implementation:

    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 for unique items:

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

非常有帮助。非常感谢!我会按照建议参加这个课程。再次感谢。 - Steve Gore

2
编译器错误是因为您需要将结果转换为列表:
moves = moves.Distinct().ToList();

然而,它可能不会按照您的期望工作,因为数组没有按照您所希望的方式定义Equals(它比较数组对象的引用,而不是数组内部的值)。请不要使用数组,创建一个类来保存您的数据,并定义EqualsGetHashCode来比较这些值。

确实,它并没有完全做到我想要的。比较数组对象的引用有什么用处?我会尝试按照你建议的定义Equals方法。 - Steve Gore

0

虽然这是一个老问题,但这里有一个使用O(1)额外空间的O(n)解决方案:

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++;
                }
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接