优化通用 AddDistinct 扩展方法

发布于 2024-10-25 00:35:40 字数 957 浏览 4 评论 0原文

我可以更有效地编写这些函数吗?

public static void AddDistinct<T>(this ICollection<T> source, 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);
}

Can I write these functions more efficient?

public static void AddDistinct<T>(this ICollection<T> source, 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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤君无依 2024-11-01 00:35:40

您可以使用 Except 方法:

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));
}

请注意,由于 WhereExcept 具有延迟和流式执行,因此您需要 ToArray()< /code> 调用以确保在向其中添加任何内容之前完成 source 的枚举(因为在枚举集合时无法对其进行修改)。

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).

記柔刀 2024-11-01 00:35:40

是的,使用例如哈希集,您可以比 O(N*M) 做得更好。

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

流心雨 2024-11-01 00:35:40

我认为使用 HashSetIEnumerable 可以更高效。 HashSet 可以高效地跟踪重复项,您只需浏览一次源即可将它们加载到集合中。除非我弄错了,否则我认为 ICollectionT[] 都是 IEnumerable 吗?

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);
    }
}

但不确定您需要这些谓词版本做什么。您不能在添加项目之前过滤它们吗?

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?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文