-1

I have two Lists

  List<Employee> previous=new List<Employee>()
        {
            new Employee()
            {
                Id = 1,
                Name = "1"
            },
            new Employee()
            {
                Id = 2,
                Name = "2"
            },
            new Employee()
            {
                Id = 6,
                Name = "6"
            },
            new Employee()
            {
                Id = 8,
                Name = "8"
            }
        };

        List<Employee> latest=new List<Employee>()
        {
            new Employee()
            {
                Id = 1,
                Name = "1"
            },
            new Employee()
            {
                Id = 3,
                Name = "3"
            },
            new Employee()
            {
                Id = 5,
                Name = "5"
            },
            new Employee()
            {
                Id = 6,
                Name = "6"
            }
        };

Now i wants to compare and want result like below which shows me which item is

  1. Added(If not present in previous and also present in latest)
  2. Removed(If present in previous and not present in latest)
  3. NoChange(If present in both previous and latest)

and it looks like

    var employeeActions = new List<EmployeeStatus>()
        {
            new EmployeeStatus()
            {
                Action = "NoChange",
                Employee = new Employee()
                {
                    Id = 1,
                    Name = "1"
                }
            },
            new EmployeeStatus(){
                Action = "Removed",
                Employee =  new Employee()
                {
                    Id = 2,
                    Name = "2"
                }
            },
            new EmployeeStatus(){
                Action = "Added",
                Employee =  new Employee()
                {
                    Id = 3,
                    Name = "3"
                }
            },
            new EmployeeStatus(){
                Action = "Added",
                Employee =   new Employee()
                {
                    Id = 5,
                    Name = "5"
                }
            },
            new EmployeeStatus(){ 
                Action = "NoChange",
                Employee = new Employee()
                {
                    Id = 6,
                    Name = "6"
                }
            },
            new EmployeeStatus(){ 
                Action = "Removed",
                Employee =  new Employee()
                {
                    Id = 8,
                    Name = "8"
                }
            }
        };

How to achieve it using LINQ to Object ?

Nilesh Moradiya
  • 651
  • 1
  • 9
  • 18

1 Answers1

1

This is difficult using LINQ to Object alone, basically all the types built into the runtime will allow you to get the following:

  • Which ones were added (use the Except extension method)
  • Which ones were removed (use the Except extension method here as well, just reverse the order of the two collections)
  • Which ones were not changed (do a join)

However, getting them in the order you want requires you to write code to do this, or use a third party library.


Disclaimer: I'm the author of DiffLib.

I have created such a third party library, DiffLib, which can do the heavy lifting. You need to do at least one of the following things though:

Once you've done that you can throw the two collections to Diff.Calculate and get resulting sections back. Sections are two types, those that contain the comparatively the same elements, or those that are different.

Here's a LINQPad program that demonstrates. You need to add DiffLib through a Nuget package.

void Main()
{
    List<Employee> previous = new List<Employee>()
    {
        new Employee() { Id = 1, Name = "1" },
        new Employee() { Id = 2, Name = "2" },
        new Employee() { Id = 6, Name = "6" },
        new Employee() { Id = 8, Name = "8" }
    };

    List<Employee> latest = new List<Employee>()
    {
        new Employee() { Id = 1, Name = "1" },
        new Employee() { Id = 3, Name = "3" },
        new Employee() { Id = 5, Name = "5" },
        new Employee() { Id = 6, Name = "6" }
    };

    var result = new List<EmployeeStatus>();
    int previousIndex = 0;
    int latestIndex = 0;
    foreach (var section in Diff.Calculate(previous, latest))
    {
        if (section.Equal)
        {
            for (int index = 0; index < section.Length1; index++)
            {
                result.Add(new EmployeeStatus { Action = "NoChange", Employee = previous[previousIndex] });
                previousIndex++;
                latestIndex++;
            }
        }
        else
        {
            for (int index = 0; index < section.Length1; index++)
            {
                result.Add(new EmployeeStatus { Action = "Removed", Employee = previous[previousIndex] });
                previousIndex++;
            }
            for (int index = 0; index < section.Length2; index++)
            {
                result.Add(new EmployeeStatus { Action = "Added", Employee = latest[latestIndex] });
                latestIndex++;
            }
        }
    }
    result.Dump();
}

public class Employee : IEquatable<Employee>
{
    public int Id { get; set; }
    public string Name { get; set; }

    public override int GetHashCode() { return Id * 23 + (Name == null ? 0 : Name.GetHashCode()); }
    public bool Equals(Employee other)
    {
        if (other == null) return false;
        if (ReferenceEquals(other, this)) return true;

        return Id == other.Id && Name == other.Name;
    }
    public override bool Equals(object other)
    {
        return Equals(other as Employee);
    }
}

public class EmployeeStatus
{
    public string Action { get; set; }
    public Employee Employee { get; set; }
}

Output:

output of example

Lasse V. Karlsen
  • 350,178
  • 94
  • 582
  • 779
  • @lasse-v-karlsen : It really helpful. – Nilesh Moradiya May 28 '15 at 11:51
  • @LasseVKarlsel may i know 'public override int GetHashCode() { return Id * 23 + (Name == null ? 0 : Name.GetHashCode()); }` what does it mean ? – Nilesh Moradiya May 28 '15 at 13:01
  • It produces a hash code for the id and name, something that dictionaries and hashsets use to identify potential matches quicker than comparing to every object. The diff algorithm uses dictionaries and hashsets internally, hence the requirement to have a valid usable hashcode. – Lasse V. Karlsen May 28 '15 at 13:02