对于C#中的alist,是否存在类似于Addrange()的AddUnique方法

我在C#中有一个列表:

var list = new List(); list.AddRange(GetGreenCars()); list.AddRange(GetBigCars()); list.AddRange(GetSmallCars()); 

问题是一些相同的汽车在不同的function中返回,我不希望它们在列表中不止一次。 每辆车都有一个唯一的Name属性。 无论如何我可以在上面有这样的东西,但只会添加项目,如果它们是独一无二的?

List似乎不是适当的集合。 您可能需要ISet实现,例如HashSet (如果需要排序,则需要SortedSet )。

为此,您需要编写一个IEqualityComparer实现,该实现根据Name属性定义汽车之间的相等性。 如果这是car-equality的’规范’定义,你也可以考虑直接将这个定义构建到Car类型本身( object.GetHashCodeobject.GetHashCode并理想地实现IEquatable )。

一种选择是添加它们并删除重复的:

 var list = new List(); list.AddRange(GetGreenCars()); list.AddRange(GetBigCars()); list.AddRange(GetSmallCars()); list = list.Distinct().ToList(); 

另一种选择是做类似的事情:

 public static void AddUnique( this IList self, IEnumerable items ) { foreach(var item in items) if(!self.Contains(item)) self.Add(item) } var list = new List(); list.AddUnique(GetGreenCars()); list.AddUnique(GetBigCars()); list.AddUnique(GetSmallCars()); 

我认为这与Tim Robbins的回答非常相似。

 var list = new List(); list.AddRange(GetGreenCars().Where(car => !list.Contains(car))); list.AddRange(GetBigCars().Where(car => !list.Contains(car))); list.AddRange(GetSmallCars().Where(car => !list.Contains(car))); 

如果你想扩展IList,我不明白为什么这对你不起作用。

使用Linq的另一个选择:

 public static void AddUnique(this IList self, IEnumerable items) { self.AddRange( items.Where(x => self.FirstOrDefault(y => y.Name == x.Name) == null).ToList()); } var list = new List(); list.AddUnique(GetGreenCars()); list.AddUnique(GetBigCars()); list.AddUnique(GetSmallCars()); 

我创建了一个扩展方法,它只为从IEnumerable实现ICollection (包括List )的任何东西添加唯一值。 与使用List.Contains() ,此方法允许您指定lambda表达式,以确定两个项是否相同。

 ///  /// Adds only items that do not exist in source. May be very slow for large collections and some types of source. ///  /// Type in the collection. /// Source collection /// Predicate to determine whether a new item is already in source. /// New items. public static void AddUniqueBy(this ICollection source, Func predicate, IEnumerable items) { foreach (T item in items) { bool existsInSource = source.Where(s => predicate(s, item)).Any(); if (!existsInSource) source.Add(item); } } 

用法:

 source.AddUniqueBy((s, i) => s.Id == i.Id, items); 

如果你想比较一个属性(在这种情况下为id),这应该有效

 var list = new List(); list.AddRange(GetGreenCars().Where(greencar => !list.Contains(greencar, car => car.id == greencar.id))); list.AddRange(GetBigCars().Where(bigcar => !list.Contains(bigcar, car => car.id == bigcar.id))); list.AddRange(GetSmallCars().Where(smallcar => !list.Contains(smallcar, car => car.id == smallcar.id))); 

如果编码器不能或不想使用Linq,则有不同的选择。

 var list = new List(); list.AddRange(GetGreenCars().FindAll((x) => !list.Contains(x))); list.AddRange(GetBigCars().FindAll((x) => !list.Contains(x))); list.AddRange(GetSmallCars().FindAll((x) => !list.Contains(x))); 

实际上,如果初始列表为空,如上例所示,您实际上可以避免在第一个AddRange()上使用FindAll(…)。