LINQ 比较两个 Genreic 相同类型的列表并获取添加、删除和未更改项目的结果
LINQ Compare Two Genreic Same Type of List and Get Result of Which item added,removed and nochange
我有两个列表
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"
}
};
现在我想比较并想要像下面这样的结果,它告诉我是哪个项目
- 已添加(如果以前不存在但最近也存在)
- 已删除(如果在以前存在但在最新不存在)
- NoChange(如果在之前和最新版本中都存在)
看起来像
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"
}
}
};
如何使用 LINQ to Object 实现?
这很难单独使用 LINQ to Object,基本上运行时内置的所有类型都可以让您获得以下内容:
- 添加了哪些(使用Except扩展方法)
- 去掉了哪些(这里也用Except扩展的方式,只是把两个集合的顺序倒过来)
- 哪些没有改变(做一个连接)
但是,按照您想要的顺序获取它们需要您编写代码来执行此操作,或者使用第三方库。
免责声明:我是DiffLib的作者。
我已经创建了这样一个第三方库,DiffLib,它可以完成繁重的工作。不过,您至少需要执行以下操作之一:
- 覆盖 Equals and GetHashCode (and preferrably also IEquatable<Employee>) 为您的
Employee
class.
- 正在编写 IEqualityComparer<Employee> 的实现。
完成后,您可以将这两个集合扔到 Diff.Calculate
并取回生成的部分。节分为两种类型,一种包含比较相同的元素,另一种包含不同的元素。
这里有一个 LINQPad 程序来演示。您需要通过 Nuget 包添加 DiffLib。
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; }
}
输出:
我有两个列表
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"
}
};
现在我想比较并想要像下面这样的结果,它告诉我是哪个项目
- 已添加(如果以前不存在但最近也存在)
- 已删除(如果在以前存在但在最新不存在)
- NoChange(如果在之前和最新版本中都存在)
看起来像
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"
}
}
};
如何使用 LINQ to Object 实现?
这很难单独使用 LINQ to Object,基本上运行时内置的所有类型都可以让您获得以下内容:
- 添加了哪些(使用Except扩展方法)
- 去掉了哪些(这里也用Except扩展的方式,只是把两个集合的顺序倒过来)
- 哪些没有改变(做一个连接)
但是,按照您想要的顺序获取它们需要您编写代码来执行此操作,或者使用第三方库。
免责声明:我是DiffLib的作者。
我已经创建了这样一个第三方库,DiffLib,它可以完成繁重的工作。不过,您至少需要执行以下操作之一:
- 覆盖 Equals and GetHashCode (and preferrably also IEquatable<Employee>) 为您的
Employee
class. - 正在编写 IEqualityComparer<Employee> 的实现。
完成后,您可以将这两个集合扔到 Diff.Calculate
并取回生成的部分。节分为两种类型,一种包含比较相同的元素,另一种包含不同的元素。
这里有一个 LINQPad 程序来演示。您需要通过 Nuget 包添加 DiffLib。
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; }
}
输出: