谁有一个快速的方法去重复在c#的泛型列表?
当前回答
我有我自己的方式。我是2循环相同的列表比较列表项。然后去掉第二个。
for(int i1 = 0; i1 < lastValues.Count; i1++)
{
for(int i2 = 0; i2 < lastValues.Count; i2++)
{
if(lastValues[i1].UserId == lastValues[i2].UserId)
{
lastValues.RemoveAt(i2);
}
}
}
其他回答
这里有一个简单的解决方案,不需要任何难读的LINQ或任何列表的预先排序。
private static void CheckForDuplicateItems(List<string> items)
{
if (items == null ||
items.Count == 0)
return;
for (int outerIndex = 0; outerIndex < items.Count; outerIndex++)
{
for (int innerIndex = 0; innerIndex < items.Count; innerIndex++)
{
if (innerIndex == outerIndex) continue;
if (items[outerIndex].Equals(items[innerIndex]))
{
// Duplicate Found
}
}
}
}
所有的答案要么复制列表,要么创建一个新列表,要么使用慢函数,要么就是慢得令人痛苦。
据我所知,这是我所知道的最快和最便宜的方法(同时,还得到了一个非常有经验的实时物理优化程序员的支持)。
// Duplicates will be noticed after a sort O(nLogn)
list.Sort();
// Store the current and last items. Current item declaration is not really needed, and probably optimized by the compiler, but in case it's not...
int lastItem = -1;
int currItem = -1;
int size = list.Count;
// Store the index pointing to the last item we want to keep in the list
int last = size - 1;
// Travel the items from last to first O(n)
for (int i = last; i >= 0; --i)
{
currItem = list[i];
// If this item was the same as the previous one, we don't want it
if (currItem == lastItem)
{
// Overwrite last in current place. It is a swap but we don't need the last
list[i] = list[last];
// Reduce the last index, we don't want that one anymore
last--;
}
// A new item, we store it and continue
else
lastItem = currItem;
}
// We now have an unsorted list with the duplicates at the end.
// Remove the last items just once
list.RemoveRange(last + 1, size - last - 1);
// Sort again O(n logn)
list.Sort();
最终成本为:
nlogn + n + nlogn = n + 2nlogn = O(nlogn)非常漂亮。
关于RemoveRange注意事项: 由于我们不能设置列表的计数并避免使用Remove函数,我不知道这个操作的确切速度,但我猜这是最快的方法。
这里有一个扩展的方法来删除相邻的副本原位。首先调用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);
}
使用HashSet可以很容易地做到这一点。
List<int> listWithDuplicates = new List<int> { 1, 2, 1, 2, 3, 4, 5 };
HashSet<int> hashWithoutDuplicates = new HashSet<int> ( listWithDuplicates );
List<int> listWithoutDuplicates = hashWithoutDuplicates.ToList();
在。net 2.0中还有另一种方法
static void Main(string[] args)
{
List<string> alpha = new List<string>();
for(char a = 'a'; a <= 'd'; a++)
{
alpha.Add(a.ToString());
alpha.Add(a.ToString());
}
Console.WriteLine("Data :");
alpha.ForEach(delegate(string t) { Console.WriteLine(t); });
alpha.ForEach(delegate (string v)
{
if (alpha.FindAll(delegate(string t) { return t == v; }).Count > 1)
alpha.Remove(v);
});
Console.WriteLine("Unique Result :");
alpha.ForEach(delegate(string t) { Console.WriteLine(t);});
Console.ReadKey();
}
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 如何使用JSON确保字符串是有效的JSON。网
- AppSettings从.config文件中获取值
- 为什么元组可以包含可变项?
- 通过HttpClient向REST API发布一个空体
- 如何检查IEnumerable是否为空或空?
- 不区分大小写的“in”
- 自动化invokerrequired代码模式
- 在c#代码中设置WPF文本框的背景颜色
- 在c#中,什么是单子?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- c#线程安全快速(est)计数器
- 如何将此foreach代码转换为Parallel.ForEach?
- 如何分裂()一个分隔字符串到一个列表<字符串>