繁体   English   中英

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

[英]Removing duplicates from string array

我是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'。 存在显式转换(您是否错过了演员?)

请帮忙? 我会非常感激的。

史蒂夫

你需要在.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

您的代码有两个错误。 第一个是对ToList的缺失调用,正如已经指出的那样。 第二是微妙的。 Unique按标识比较对象,但重复的列表项具有不同的数组实例。

该问题有多种解决方案。

  • moves.Distinct().ToList()使用自定义相等比较器。 无需进一步更改。

    示例实施:

     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()); } } 

    过滤独特的项目:

     moves = moves.Distinct(new ArrayEqualityComparer<string>()).ToList(); 
  • 使用Tuple <string,string,string>而不是string[] 元组提供内置的结构平等和比较。 由于长类型名称,此变体可能会使代码混乱。

    实例:

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

    添加新动作:

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

    过滤独特的项目:

     moves = moves.Distinct().ToList(); 
  • 使用自定义类来保存三个值。 我实际上推荐这个变种,因为它使你处理动作的所有代码更具可读性。

    示例实施:

     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 } 

    实例:

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

    添加新动作:

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

    过滤独特的项目:

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

编译器错误是因为您需要将结果转换为列表:

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

但是它可能无法正常工作,因为数组没有以您希望的方式定义的Equals (它比较数组对象的引用,而不是数组中的值)。 不是使用数组,而是创建一个类来保存数据并定义EqualsGetHashCode来比较值。

老问题,但这是使用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++;
                }
            }
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM