2014-09-19 8 views
1

Я хочу сравнить два списка объектов. Эти списки содержат один и тот же тип объектов. Я создаю новый список в моей программе, и я хочу сравнить его со старым списком, который находится в базе данных. Я получаю его с хранимой процедурой, затем я помещаю ее в объект.Сравнить два списка объектов C#

The old list :      the new list : 

*Category 1*       Category 5 
*Category 2*       Category 6 
*Category 3*       *Category 4* 
Category 4 

Здесь цель состоит в том, чтобы удалить первые три категории в старом списке, обусловленно они не существуют в новом списке. И до удалите категорию 4 в новом списке, потому что категория 4 уже существует в старом списке.

Можно использовать такой метод, как Equals(), или использовать два цикла foreach для просмотра списков?

Спасибо за вас ответы и советы

+0

Вы пробовали '.Except()' метод расширения? –

+0

Я пробовал это, но проблема в том, что я не использую все свойства объекта, и он не работает. Можно выбрать свойства для сравнения? – Julien698

+1

Метод Except() может принимать IEqualityComparer (http://msdn.microsoft.com/en-us/library/vstudio/ms132151%28v=vs.100%29.aspx), который вы должны реализовать. Он должен выполнить сравнение, которое вы хотите. –

ответ

3

Вы можете использовать LINQ, except и where

var a = new List<string> { "a", "b", "c" }; 
var b = new List<string> { "c", "d", "e" }; 
var temp = a.Intersect(b).ToList(); 
b = b.Except(a).ToList(); 
a = temp; 

Выход:

a: "c" 
b: "d", "e" 

Примечание: Это, вероятно, более эффективно делать это без LINQ

var a = new List<string> { "a", "b", "c" }; 
var b = new List<string> { "c", "d", "e" }; 

for(int i = 0; i < a.Count; i++) 
    if(b.Contains(a[i])) 
     b.Remove(a[i]); 
    else 
     a.Remove(a[i--]); 

Если вы необходимо сравнивать на основе определенного значения

for(int i = 0; i < a.Count; i++) 
{ 
    var obj = b.Where(item => item.Category == a[i].Category); 
    if(obj.Any()) 
     b.Remove(obj.First()); 
    else 
     a.Remove(a[i--]); 
} 
+2

Вы можете использовать 'Intersect' вместо комбинации' Where'/'Contains'. Например: 'var temp = a.Intersect (b) .ToList();' – LukeH

+0

@LukeH - Спасибо, я забыл о 'Intersect' – Sayse

+0

Это хорошая идея, он отлично работает, но у меня есть другая проблема, так это то, что объекты свойства не совпадают. Например, у меня есть Title = Category1, Id = 2, rank = 4, а другой Title = Category1, Id = 2, rank = 0. Из-за Ранга это не совпадает. Я думаю, что я исправлю проблему ранга, ставя его в ноль все время! – Julien698

0

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

+0

Что заставляет вас думать, что они сортируются? – Rawling

1

Это не самая красивая из реализаций, но самый быстрый способ, которым Вы можете сделать это:

var tempA = new HashSet<int>(inputA.Select(item => item.Id)); 
var tempB = new HashSet<int>(inputB.Select(item => item.Id)); 

var resultA = new List<Category>(inputA.Count); 
var resultB = new List<Category>(inputB.Count); 

foreach (var value in inputA) 
    if (tempB.Contains(value.Id)) 
     resultA.Add(value); 

foreach (var value in inputB) 
    if (!tempA.Contains(value.Id)) 
     resultB.Add(value); 

resultA.TrimExcess(); 
resultB.TrimExcess(); 

// and if needed: 
inputA = resultA; 
inputB = resultB; 

Если вам нужно больше, чем item.id как уникальный затем использовать новый кортеж, такие как:

inputA.Select(item => new Tuple<int, string>(item.Id, item.Title)); 

Другой вариант заключается в переопределении .GetHashCode в вашей категории класса, такие как:

public override int GetHashCode() 
{ 
    return Id.GetHashCode(); 
} 

public override bool Equals(object obj) 
{ 
    var typedObj = obj as Category; 
    if (typedObj == null) 
     return false; 
    return Title == typedObj.Title && Id == typedObj.Id && Rank == typedObj.Rank; 
} 
Смежные вопросы