C # объединить отдельные элементы из 2 коллекций - PullRequest
7 голосов
/ 13 мая 2011

Я ищу эффективный способ добавить отдельные элементы второй коллекции ICollection к существующей.Я использую .NET 4.

Ответы [ 4 ]

13 голосов
/ 13 мая 2011

Это должно сделать это:

list1.Union(list2).Distinct(aCustomComparer).ToList()
6 голосов
/ 13 мая 2011

Пока они IEnumerable, вы можете использовать переходный ответ Linq:

var union = firstCollection.Union(secondCollection);

Это будет использовать сравнение равенства по умолчанию, которое для большинства объектов является ссылочным равенством. Чтобы изменить это, вы можете определить универсальный IEqualityComparer для типа элемента в вашей коллекции, который будет выполнять более семантическое сравнение, и указать его как второй аргумент Union.

2 голосов
/ 13 мая 2011

Самый прямой ответ на ваш вопрос - поскольку вы не предоставили подробных сведений о реальных типах ICollection, которые вы используете в качестве входных данных или нужных в качестве выходных данных, предоставлены KeithS

var union = firstCollection.Union(secondCollection);

Это вернет отличный IEnumerable - если это то, что вам нужно, то это ОЧЕНЬ быстро. Я сделал небольшое тестовое приложение (ниже), которое запустило метод объединения (MethodA) по сравнению с простым методом дедупликации хэш-набора и возвращает Hashset <> (MethodB). Метод объединения УНИЧТОЖАЕТ хэш-сет:

Метод A: 1 мс

Метод B: 2827мс

Однако - необходимость преобразования этого IEnumerable в другой тип коллекции, такой как List <> (например, в опубликованную версию ADas), меняет все:

Простое добавление .ToList () к MethodA

var union = firstCollection.Union(secondCollection).ToList();

Изменяет результаты:

Метод А: 3656мс

Метод B: 2803мс

Итак - кажется, что нужно больше знать о конкретном случае, с которым вы работаете, - и любое решение, которое вы придумали, должно быть проверено - так как небольшое (кодовое) изменение может иметь ОГРОМНОЕ воздействие.

Ниже приведен тест, который я использовал для сравнения этих методов - я уверен, что это глупый способ тестирования - но, похоже, он работает:)

    private static void Main(string[] args)
    {
        ICollection<string> collectionA = new List<string>();
        ICollection<string> collectionB = new List<string>();
        for (int i = 0; i < 1000; i++)
        {
            string randomString = Path.GetRandomFileName();
            collectionA.Add(randomString);
            collectionA.Add(randomString);
            collectionB.Add(randomString);
            collectionB.Add(randomString);
        }
        Stopwatch testA = new Stopwatch();
        testA.Start();
        MethodA(collectionA, collectionB);
        testA.Stop();


        Stopwatch testB = new Stopwatch();
        testB.Start();
        MethodB(collectionA, collectionB);
        testB.Stop();

        Console.WriteLine("MethodA: {0}ms", testA.ElapsedMilliseconds);
        Console.WriteLine("MethodB: {0}ms", testB.ElapsedMilliseconds);
        Console.ReadLine();
    }

    private static void MethodA(ICollection<string> collectionA, ICollection<string> collectionB)
    {
        for (int i = 0; i < 10000; i++)
        {
            var result = collectionA.Union(collectionB);
        }
    }

    private static void MethodB(ICollection<string> collectionA, ICollection<string> collectionB)
    {
        for (int i = 0; i < 10000; i++)
        {
            var result = new HashSet<string>(collectionA);
            foreach (string s in collectionB)
            {
                result.Add(s);
            }
        }
    }
2 голосов
/ 13 мая 2011

Еще один способ добавить в ваш существующий список будет:

list1.AddRange(list2.Distinct().Except(list1));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...