开发者

Optimizing generic AddDistinct extension method

开发者 https://www.devze.com 2023-02-19 09:20 出处:网络
Can I write these functions more efficient? public static void AddDistinct<T>(this ICollection<T> sourc开发者_如何学Pythone, params ICollection<T>[] collections)

Can I write these functions more efficient?

public static void AddDistinct<T>(this ICollection<T> sourc开发者_如何学Pythone, params ICollection<T>[] collections)
{
    (from collection in collections from item in collection where !source.Contains(item) select item).ForEach(source.Add);
}

public static void AddDistinct<T>(this ICollection<T> source, Func<T, bool> predicate, params ICollection<T>[] collections)
{
    collections.ForEach(collection => collection.Where(predicate).Where(item => !source.Contains(item)).ForEach(source.Add));
}

public static void AddDistinct<T>(this ICollection<T> source, params T[] items)
{
    items.Where(item => !source.Contains(item)).ForEach(source.Add);
}

public static void AddDistinct<T>(this ICollection<T> source, Func<T, bool> predicate, params T[] items)
{
    items.Where(predicate).Where(x => !source.Contains(x)).ForEach(source.Add);
}


You can use the Except method:

public static void AddDistinct<T>(this ICollection<T> source, params ICollection<T>[] collections)
{
    var itemsToAdd = collections.SelectMany(x => x).Where(predicate).Except(source).ToArray();
    itemsToAdd.ForEach(source.Add));
}

public static void AddDistinct<T>(this ICollection<T> source, Func<T, bool> predicate, params ICollection<T>[] collections)
{
    var itemsToAdd = collections.SelectMany(x => x).Where(predicate).Except(source).ToArray();
    itemsToAdd.ForEach(source.Add));
}

public static void AddDistinct<T>(this ICollection<T> source, params T[] items)
{
    var itemsToAdd = items.Except(source).ToArray();
    itemsToAdd.ForEach(source.Add));
}

public static void AddDistinct<T>(this ICollection<T> source, Func<T, bool> predicate, params T[] items)
{
    var itemsToAdd = items.Where(predicate).Except(source).ToArray();
    itemsToAdd.ForEach(source.Add));
}

Note that because Where and Except have deferred and streamed execution, you need the ToArray() call to ensure the enumeration of source is complete before you add anything to it (since a collection can't be modified while it's being enumerated).


Yes, using e.g. a hashset you can do much better than O(N*M).


Using HashSet<T> and IEnumerable<T> you can do it more efficient I think. The HashSet is efficient at keeping track of duplicates, and you only need to go through the source once to load them into the set. And unless I'm mistaken, I think both ICollection<T> and T[] are IEnumerable<T>s?

public static void AddDistinct<T>(this ICollection<T> source, params IEnumerable<T> items)
{
    var set = new HashSet<T>(source);
    foreach(var item in items)
    {
        if(set.Add(item))
            source.Add(item);
    }
}

Not sure what you need those predicate versions for though. Can't you just filter your items before you add them?

0

精彩评论

暂无评论...
验证码 换一张
取 消