删除C#中List <T>的重复项
任何人都有一个快速的方法去重复C#中的通用列表?
也许你应该考虑使用HashSet 。
从MSDN链接:
using System; using System.Collections.Generic; class Program { static void Main() { HashSet<int> evenNumbers = new HashSet<int>(); HashSet<int> oddNumbers = new HashSet<int>(); for (int i = 0; i < 5; i++) { // Populate numbers with just even numbers. evenNumbers.Add(i * 2); // Populate oddNumbers with just odd numbers. oddNumbers.Add((i * 2) + 1); } Console.Write("evenNumbers contains {0} elements: ", evenNumbers.Count); DisplaySet(evenNumbers); Console.Write("oddNumbers contains {0} elements: ", oddNumbers.Count); DisplaySet(oddNumbers); // Create a new HashSet populated with even numbers. HashSet<int> numbers = new HashSet<int>(evenNumbers); Console.WriteLine("numbers UnionWith oddNumbers..."); numbers.UnionWith(oddNumbers); Console.Write("numbers contains {0} elements: ", numbers.Count); DisplaySet(numbers); } private static void DisplaySet(HashSet<int> set) { Console.Write("{"); foreach (int i in set) { Console.Write(" {0}", i); } Console.WriteLine(" }"); } } /* This example produces output similar to the following: * evenNumbers contains 5 elements: { 0 2 4 6 8 } * oddNumbers contains 5 elements: { 1 3 5 7 9 } * numbers UnionWith oddNumbers... * numbers contains 10 elements: { 0 2 4 6 8 1 3 5 7 9 } */
如果你使用.Net 3+,你可以使用Linq。
List<T> withDupes = LoadSomeData(); List<T> noDupes = withDupes.Distinct().ToList();
怎么样:-
var noDupes = list.Distinct().ToList();
在.net 3.5中?
简单地用一个相同types的List来初始化一个HashSet:
var noDupes = new HashSet<T>(withDupes);
或者,如果您想要返回一个列表:
var noDupsList = new HashSet<T>(withDupes).ToList();
对它进行sorting,然后检查相邻的两个和两个,因为重复项将会聚集在一起。
像这样的东西:
list.Sort(); Int32 index = 0; while (index < list.Count - 1) { if (list[index] == list[index + 1]) list.RemoveAt(index); else index++; }
它为我工作。 简单地使用
List<Type> liIDs = liIDs.Distinct().ToList<Type>();
用你想要的typesreplace“Type”,例如int。
正如kronoz在.net 3.5中所说,你可以使用Distinct()
。
在.Net 2中,你可以模仿它:
public IEnumerable<T> DedupCollection<T> (IEnumerable<T> input) { var passedValues = new HashSet<T>(); // Relatively simple dupe check alg used as example foreach(T item in input) if(passedValues.Add(item)) // True if item is new yield return item; }
这可以用来重复删除任何集合,并将返回原始顺序的值。
过滤集合通常要快得多(正如Distinct()
和本示例所做的那样),而不是从中删除项目。
我喜欢使用这个命令:
List<Store> myStoreList = Service.GetStoreListbyProvince(provinceId) .GroupBy(s => s.City) .Select(grp => grp.FirstOrDefault()) .OrderBy(s => s.City) .ToList();
我在我的列表中有这些字段:Id,StoreName,City,PostalCode我想显示具有重复值的下拉列表中的城市列表。 解决方法:按城市分组,然后select第一个列表。
我希望它有助于:)
一个扩展方法可能是一个体面的方式去…这样的事情:
public static List<T> Deduplicate<T>(this List<T> listToDeduplicate) { return listToDeduplicate.Distinct().ToList(); }
然后像这样打电话,例如:
List<int> myFilteredList = unfilteredList.Deduplicate();
在Java中(我假设C#或多或less是相同的):
list = new ArrayList<T>(new HashSet<T>(list))
如果你真的想改变原来的列表:
List<T> noDupes = new ArrayList<T>(new HashSet<T>(list)); list.clear(); list.addAll(noDupes);
为了保持顺序,只需用LinkedHashSetreplaceHashSet即可。
作为一个辅助方法(没有Linq):
public static List<T> Distinct<T>(this List<T> list) { return (new HashSet<T>(list)).ToList(); }
以下是一个扩展方法,用于在原位删除相邻的重复项。 先调用Sort()并传入相同的IComparer。 这应该比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
,如果你想维护订单,你可以这样做:
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)
空间,而sorting,然后使独特的(由@ lassevk等人build议)是O(N*lgN)
时间和O(1)
空间,所以它不是对我来说很清楚(乍看之下),sorting的方式是次要的(我对暂时的决定表示歉意)
可能会更容易,只需确保重复项不会添加到列表中。
if(items.IndexOf(new_item) < 0) items.add(new_item)
在.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(); }
有很多方法可以解决 – 列表中的重复问题,下面是其中之一:
List<Container> containerList = LoadContainer();//Assume it has duplicates List<Container> filteredList = new List<Container>(); foreach (var container in containerList) { Container duplicateContainer = containerList.Find(delegate(Container checkContainer) { return (checkContainer.UniqueId == container.UniqueId); }); //Assume 'UniqueId' is the property of the Container class on which ur making a search if(!containerList.Contains(duplicateContainer) //Add object when not found in the new class object { filteredList.Add(container); } }
干杯Ravi Ganesan
通过Nuget安装MoreLINQ包,您可以轻松地通过属性区分对象列表
IEnumerable<Catalouge> distinctCatalouges = catalouges.DistinctBy(c => c.CatalougeCode);
这是一个简单的解决scheme,不需要任何难以阅读的LINQ或任何先前的列表sorting。
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 } } } }
大卫J.的答案是一个好方法,不需要额外的对象,sorting等,但可以改善:
for (int innerIndex = items.Count - 1; innerIndex > outerIndex ; innerIndex--)
因此,外部循环遍历整个列表的顶部底部,但内部循环到底部“直到外部循环位置到达”。
外层循环确保整个列表被处理,内层循环find实际的重复,这些只能发生在外层循环尚未处理的部分。
或者,如果你不想自下而上的内部循环,你可以让内部循环开始在outerIndex + 1。
public static void RemoveDuplicates<T>(IList<T> list ) { if (list == null) { return; } int i = 1; while(i<list.Count) { int j = 0; bool remove = false; while (j < i && !remove) { if (list[i].Equals(list[j])) { remove = true; } j++; } if (remove) { list.RemoveAt(i); } else { i++; } } }
你可以使用联盟
obj2 = obj1.Union(obj1).ToList();