Простой способ сравнить два списка <String>и сохранить только уникальные значения - PullRequest
1 голос
/ 15 марта 2012

Я пытаюсь сравнить два списка и сохранить в каждом списке только элементы, уникальные для каждого списка.Не могли бы вы помочь?

Я знаю, как сделать пересечение, но на самом деле мне нужно сделать наоборот

        //Example
        List<String> baseListCopy = new List<String>();
        baseListCopy.Add("Test1");
        baseListCopy.Add("Test2");
        baseListCopy.Add("Test3");
        baseListCopy.Add("Test4");
        baseListCopy.Add("Test5");
        baseListCopy.Add("Test6");
        baseListCopy.Add("Test7");
        baseListCopy.Add("Test8");
        baseListCopy.Add("Test9");

        List<String> resultListCopy = new List<String>();
        resultListCopy.Add("Test1");
        resultListCopy.Add("Test2");
        resultListCopy.Add("Test3");
        resultListCopy.Add("Test40");
        resultListCopy.Add("Test90");

        //returns only items that are present on both lists
        resultListCopy = baseListCopy.Intersect(resultListCopy, StringComparer.InvariantCultureIgnoreCase).ToList();

        //How do I return only items that are unique to that list?

Ответы [ 5 ]

7 голосов
/ 15 марта 2012

Ваш вопрос неясен.

Звучит так, будто вы хотите, чтобы все элементы отображались в одном списке (XOR):

a.Union(b).Except(a.Intersect(b))
3 голосов
/ 15 марта 2012

Непонятно, что вы подразумеваете под "этим списком", но я думаю, что вы хотите Except:

// Just to avoid scrolling :)
var comparer = StringComparer.InvariantCultureIgnoreCase;
var baseListOnly = baseListCopy.Except(resultListCopy, comparer)
                               .ToList();

Обратите внимание, что заполнять списки гораздо проще, используя инициализаторы коллекций:

List<String> baseListCopy = new List<String> { 
    "Test1", "Test2", "Test3",
    "Test4", ...
};

Если вы на самом деле после элементов, которые находятся точно в одном списке, тогда другой альтернативой ответа SLaks будет использование HashSet<T>.SymmetricExceptWith:

var hashSet = new HashSet<string>(baseListCopy,  
                                  StringComparer.InvariantCultureIgnoreCase);
// This mutates the set
hashSet.SymmetricExceptWith(resultListCopy);
2 голосов
/ 15 марта 2012

Чтобы получить все результаты, которые не содержатся в resultListCopy:

resultListCopy = baseListCopy.Except(resultListCopy, StringComparer.InvariantCultureIgnoreCase)
                             .ToList();
1 голос
/ 15 марта 2012

Небольшой вариант сообщения SLaks:

var finalListCopy = 
  baseListCopy.Except(resultListCopy).Union(resultListCopy.Except(baseListCopy));

Две исключения, объединенные в Союз ...: D

1 голос
/ 15 марта 2012

Почему бы вам не взять пересечение и не выполнить итерацию по нему, удаляя каждое значение из базы, находящейся в пересечении.Попробуйте:

resultListCopy = baseListCopy.Intersect(resultListCopy, StringComparer.InvariantCultureIgnoreCase).ToList();
resultList = new List<String>();
foreach (string s in resultListCopy )
{
    if (!baseListCopy.contains(s))
        resultList.add(s);
}

Или с помощью resultListCopy и замены базового List, если вы это имели в виду.

...