Julien698
Julien698

Reputation: 716

Compare two list of objects C#

I want to compare two list of objects. These lists contains the same type of objects. I create a new List in my programme and i want to compare it at the old list which is in the database. I get it with a stored procedure, then i put it into an object.

The old list :                     the new list :

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

Here the aim is to delete the first three Category in the old list, beacause they don't exist in the new list. And to delete the Category 4 in the new list because category 4 already exists in the old list.

It is possible to use à method like Equals() or use two foreach loop to browse the lists ?

Thanks for you answers and advises

Upvotes: 1

Views: 8371

Answers (3)

Seph
Seph

Reputation: 8693

It's not the most pretty of implementations but the fastest way you can do this is:

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;

If you need more than item.id as unique then use a new Tuple such as:

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

Another option is to override .GetHashCode in your category class such as:

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

Upvotes: 1

Sayse
Sayse

Reputation: 43300

You can use the linq, except and 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;

Output:

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

Note: It is probably more efficient to do this without 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--]);

If you need to compare based on a particular value

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

Upvotes: 4

Konstantin Dinev
Konstantin Dinev

Reputation: 34895

I would solve this by sorting the two list and iterating over the first and second list. I would compare the current item of the first list to the current item from the second. If a match is found I remove the match from the second list and I move to the next item in both lists, otherwise the current item of the first list is removed from it and the iteration continues in the first list.

Upvotes: 0

Related Questions