谁有一个快速的方法去重复在c#的泛型列表?
当前回答
使用HashSet: list = new HashSet<T>(list).ToList();
其他回答
如果你不关心顺序,你可以把这些项推到HashSet中,如果你想保持顺序,你可以这样做:
var unique = new List<T>();
var hs = new HashSet<T>();
foreach (T t in list)
if (hs.Add(t))
unique.Add(t);
或者用Linq的方式:
var hs = new HashSet<T>();
list.All( x => hs.Add(x) );
编辑:HashSet方法是O(N)时间和O(N)空间,而排序,然后使唯一(由@lassevk和其他人建议)是O(N*lgN)时间和O(1)空间,所以我不太清楚(因为它是第一眼),排序方式是较差的
我喜欢使用这个命令:
List<Store> myStoreList = Service.GetStoreListbyProvince(provinceId)
.GroupBy(s => s.City)
.Select(grp => grp.FirstOrDefault())
.OrderBy(s => s.City)
.ToList();
我的列表中有这些字段:Id、StoreName、City、PostalCode 我想在一个有重复值的下拉列表中显示城市。 解决方案:按城市分组,然后选择列表中的第一个城市。
如果需要比较复杂的对象,则需要在Distinct()方法中传递一个compararer对象。
private void GetDistinctItemList(List<MyListItem> _listWithDuplicates)
{
//It might be a good idea to create MyListItemComparer
//elsewhere and cache it for performance.
List<MyListItem> _listWithoutDuplicates = _listWithDuplicates.Distinct(new MyListItemComparer()).ToList();
//Choose the line below instead, if you have a situation where there is a chance to change the list while Distinct() is running.
//ToArray() is used to solve "Collection was modified; enumeration operation may not execute" error.
//List<MyListItem> _listWithoutDuplicates = _listWithDuplicates.ToArray().Distinct(new MyListItemComparer()).ToList();
return _listWithoutDuplicates;
}
假设你有另外两个类,比如:
public class MyListItemComparer : IEqualityComparer<MyListItem>
{
public bool Equals(MyListItem x, MyListItem y)
{
return x != null
&& y != null
&& x.A == y.A
&& x.B.Equals(y.B);
&& x.C.ToString().Equals(y.C.ToString());
}
public int GetHashCode(MyListItem codeh)
{
return codeh.GetHashCode();
}
}
And:
public class MyListItem
{
public int A { get; }
public string B { get; }
public MyEnum C { get; }
public MyListItem(int a, string b, MyEnum c)
{
A = a;
B = b;
C = c;
}
}
这里有一个扩展的方法来删除相邻的副本原位。首先调用Sort()并传入相同的ic比较器。这应该比Lasse V. Karlsen的版本更有效,后者重复调用RemoveAt(导致多次块内存移动)。
public static void RemoveAdjacentDuplicates<T>(this List<T> List, IComparer<T> Comparer)
{
int NumUnique = 0;
for (int i = 0; i < List.Count; i++)
if ((i == 0) || (Comparer.Compare(List[NumUnique - 1], List[i]) != 0))
List[NumUnique++] = List[i];
List.RemoveRange(NumUnique, List.Count - NumUnique);
}
在Java中(我认为c#或多或少是相同的):
list = new ArrayList<T>(new HashSet<T>(list))
如果你真的想改变原来的列表:
List<T> noDupes = new ArrayList<T>(new HashSet<T>(list));
list.clear();
list.addAll(noDupes);
为了保持顺序,只需将HashSet替换为LinkedHashSet。
推荐文章
- 在每个列表元素上调用int()函数?
- 如何从枚举中选择一个随机值?
- 将Set<T>转换为List<T>的最简洁的方法
- 驻留在App_Code中的类不可访问
- 在链式LINQ扩展方法调用中等价于'let'关键字的代码
- dynamic (c# 4)和var之间的区别是什么?
- Visual Studio: ContextSwitchDeadlock
- 返回文件在ASP。Net Core Web API
- 自定义HttpClient请求头
- 在Python中插入列表的第一个位置
- 如果我使用OWIN Startup.cs类并将所有配置移动到那里,我是否需要一个Global.asax.cs文件?
- VS2013外部构建错误"error MSB4019: The imported project <path> was not found"
- 在javascript中从平面数组构建树数组
- 从另一个列表id中排序一个列表
- 等待一个无效的异步方法