我是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'。存在显式转换(您是否错过了演员?)
请帮忙吗?我会非常感激。
史蒂夫
答案 0 :(得分:3)
您需要在.ToList()
方法后调用.Distinct
,因为它返回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
答案 1 :(得分:3)
您的代码有两个错误。第一个是对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();
使用元组<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();
答案 2 :(得分:2)
编译错误是因为您需要将结果转换为列表:
moves = moves.Distinct().ToList();
然而,它可能无法正常工作,因为数组没有以您希望的方式定义Equals
(它比较数组对象的引用,而不是数组中的值) 。不要使用数组,而是创建一个类来保存数据,并定义Equals
和GetHashCode
来比较值。
答案 3 :(得分: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++;
}
}
}
}