Оптимизация общего метода расширения AddDistinct - PullRequest
1 голос
/ 23 марта 2011

Могу ли я написать эти функции более эффективно?

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

Ответы [ 3 ]

2 голосов
/ 23 марта 2011

Да, используя, например, хэш-сет, вы можете сделать намного лучше, чем O(N*M).

2 голосов
/ 23 марта 2011

Используя HashSet<T> и IEnumerable<T>, я думаю, вы можете сделать это более эффективно.HashSet эффективен для отслеживания дубликатов, и вам нужно всего лишь один раз пройтись по источнику, чтобы загрузить их в набор.И если я не ошибаюсь, я думаю, что и ICollection<T>, и T[] являются IEnumerable<T> с?

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

.Разве вы не можете просто отфильтровать свои вещи, прежде чем добавить их?

2 голосов
/ 23 марта 2011

Вы можете использовать метод 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));
}

Обратите внимание, что поскольку Where и Except имеют отложенное и потоковое выполнение, вам необходим вызов ToArray(), чтобы обеспечить перечисление source завершено до того, как вы добавите к нему что-либо (поскольку коллекция не может быть изменена во время перечисления).

...