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

leo*_*ora 30 c# collections unique

我在C#中有一个列表:

       var list = new List<Car>();
       list.AddRange(GetGreenCars());
       list.AddRange(GetBigCars());
       list.AddRange(GetSmallCars());
Run Code Online (Sandbox Code Playgroud)

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

Ivo*_*Ivo 47

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

var list = new List<Car>();
list.AddRange(GetGreenCars());
list.AddRange(GetBigCars());
list.AddRange(GetSmallCars());
list = list.Distinct().ToList();
Run Code Online (Sandbox Code Playgroud)

  • Distinct将删除重复的对象.如果你的对象实际上不一样,你必须使你的对象实现Equals()和GetHashCode() (4认同)

Ivo*_*Ivo 25

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

public static void AddUnique<T>( this IList<T> self, IEnumerable<T> items )
{
    foreach(var item in items)
        if(!self.Contains(item))
            self.Add(item);
}


var list = new List<Car>();
list.AddUnique(GetGreenCars());
list.AddUnique(GetBigCars());
list.AddUnique(GetSmallCars());
Run Code Online (Sandbox Code Playgroud)


Ani*_*Ani 18

A List<T>似乎不是这里的合适集合.您可能想要一个ISet<T>实现,如HashSet<T>(或SortedSet<T>如果您需要订购).

为此,您需要编写一个IEqualityComparer<T>实现,根据Name属性定义汽车之间的相等性.如果这是汽车平等的"规范"的定义,你也可以直接考虑建设这个定义为Car类型本身(object.Equals,object.GetHashCode理想情况下实现IEquatable<T>过).


Jos*_*ust 11

给你覆盖.Equals()的方法Car来确定一个汽车对象是一样的另一辆汽车的对象,那么下面应该工作的W/O写的扩展方法.

    var list = new List<Car>();
    list.AddRange(GetGreenCars()?.Except(list) ?? new List<Car>());
    list.AddRange(GetBigCars()?.Except(list) ?? new List<Car>());
    list.AddRange(GetSmallCars()?.Except(list) ?? new List<Car>());
Run Code Online (Sandbox Code Playgroud)

  • 你可以稍微缩短它:`GetGreenCars().除了(列表)` (2认同)

Tim*_*ins 5

使用Linq的另一个选择:

public static void AddUnique<T>(this IList<T> self, IEnumerable<T> items)
{
  self.AddRange(
    items.Where(x => self.FirstOrDefault(y => y.Name == x.Name) ==
    null).ToList());
}

var list = new List<Car>();
list.AddUnique(GetGreenCars());
list.AddUnique(GetBigCars());
list.AddUnique(GetSmallCars());
Run Code Online (Sandbox Code Playgroud)


Eri*_* J. 5

我创造了只添加唯一值的任何实现的扩展方法ICollection<T>(包括List<T>从)IEnumerable<T>。与使用 的实现不同List<T>.Contains(),此方法允许您指定一个 lambda 表达式来确定两个项目是否相同。

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

用法:

source.AddUniqueBy<Foo>((s, i) => s.Id == i.Id, items);
Run Code Online (Sandbox Code Playgroud)