C# 快速获取两个列表之间差异的方法<&燃气轮机;物体
如何使C# 快速获取两个列表之间差异的方法<&燃气轮机;物体,c#,list,C#,List,如何使itemsToRemove仅包含“bar-one”,而itemsToAdd仅包含“bar-five” 我试图使用“除外”,但显然我用错了 var oldList = new List<Foo>(); oldList.Add(new Foo(){ Bar = "bar one"}); oldList.Add(new Foo(){ Bar = "bar two"}); oldList.Add(new Foo(){ Bar = "bar three"}); oldList.Add(n
itemsToRemove
仅包含“bar-one”,而itemsToAdd
仅包含“bar-five”
我试图使用“除外”,但显然我用错了
var oldList = new List<Foo>();
oldList.Add(new Foo(){ Bar = "bar one"});
oldList.Add(new Foo(){ Bar = "bar two"});
oldList.Add(new Foo(){ Bar = "bar three"});
oldList.Add(new Foo(){ Bar = "bar four"});
var newList = new List<Foo>();
newList.Add(new Foo(){ Bar = "bar two"});
newList.Add(new Foo(){ Bar = "bar three"});
newList.Add(new Foo(){ Bar = "bar four"});
newList.Add(new Foo(){ Bar = "bar five"});
var itemsToRemove = oldList.Except(newList); // should only contain "bar one"
var itemsToAdd = newList.Except(oldList); // should only contain "bar one"
foreach(var item in itemsToRemove){
Console.WriteLine(item.Bar + " removed");
// currently says
// bar one removed
// bar two removed
// bar three removed
// bar four removed
}
foreach(var item in itemsToAdd){
Console.WriteLine(item.Bar + " added");
// currently says
// bar two added
// bar three added
// bar four added
// bar five added
}
var oldList=新列表();
Add(newfoo(){Bar=“Bar one”});
Add(newfoo(){Bar=“Bar two”});
Add(newfoo(){Bar=“Bar three”});
Add(newfoo(){Bar=“Bar four”});
var newList=新列表();
Add(newfoo(){Bar=“Bar two”});
Add(newfoo(){Bar=“Bar three”});
Add(newfoo(){Bar=“Bar four”});
Add(newfoo(){Bar=“Bar-five”});
var itemsToRemove=oldList.Except(newList);//应仅包含“第一栏”
var itemsToAdd=newList.Except(oldList);//应仅包含“第一栏”
foreach(itemsToRemove中的变量项){
控制台写入线(item.Bar+“已删除”);
//现在说
//一号杆已拆除
//删除第二条
//三号杆已拆除
//删除第四栏
}
foreach(itemsToAdd中的var项){
控制台写入线(item.Bar+“添加”);
//现在说
//增加了第二栏
//增加了第三栏
//增加了第四栏
//增加第五栏
}
这是因为您正在比较类型为Foo
的对象,而不是类型为string
的属性栏。尝试:
var itemsToRemove = oldList.Select(i => i.Bar).Except(newList.Select(i => i.Bar));
var itemsToAdd = newList.Select(i => i.Bar).Except(oldList.Select(i => i.Bar));
这是因为您正在比较类型为
Foo
的对象,而不是类型为string
的属性栏。尝试:
var itemsToRemove = oldList.Select(i => i.Bar).Except(newList.Select(i => i.Bar));
var itemsToAdd = newList.Select(i => i.Bar).Except(oldList.Select(i => i.Bar));
Except
将使用相关对象的默认Equals
和GetHashCode
方法来定义对象的“相等”,除非您提供了自定义比较器(尚未提供)。在这种情况下,这将比较对象的引用,而不是它们的Bar
值
一个选项是创建一个比较条
属性的IEqualityComparer
,而不是对对象本身的引用
public class FooComparer : IEqualityComparer<Foo>
{
public bool Equals(Foo x, Foo y)
{
if (x == null ^ y == null)
return false;
if (x == null && y == null)
return true;
return x.Bar == y.Bar;
}
public int GetHashCode(Foo obj)
{
if (obj == null)
return 0;
return obj.Bar.GetHashCode();
}
}
这使我们能够写:
var itemsToRemove = oldList.ExceptBy(newList, foo => foo.Bar);
var itemsToAdd = newList.ExceptBy(oldList, foo => foo.Bar);
Except
将使用相关对象的默认Equals
和GetHashCode
方法来定义对象的“相等”,除非您提供了自定义比较器(尚未提供)。在这种情况下,这将比较对象的引用,而不是它们的Bar
值
一个选项是创建一个比较条
属性的IEqualityComparer
,而不是对对象本身的引用
public class FooComparer : IEqualityComparer<Foo>
{
public bool Equals(Foo x, Foo y)
{
if (x == null ^ y == null)
return false;
if (x == null && y == null)
return true;
return x.Bar == y.Bar;
}
public int GetHashCode(Foo obj)
{
if (obj == null)
return 0;
return obj.Bar.GetHashCode();
}
}
这使我们能够写:
var itemsToRemove = oldList.ExceptBy(newList, foo => foo.Bar);
var itemsToAdd = newList.ExceptBy(oldList, foo => foo.Bar);
您的逻辑是合理的,但比较两个类的默认行为是按引用进行。由于您可以有效地创建两个包含8个不同对象(无论其内容如何)的列表,因此不会有两个相等的对象 但是,您可以使用。例如:
public class FooEqualityComparer : IEqualityComparer<Foo>
{
public bool Equals(Foo left, Foo right)
{
if(left == null && right == null) return true;
return left != null && right != null && left.Bar == right.Bar;
}
public int GetHashCode(Foo item)
{
return item != null ? item.Bar.GetHashcode() : 0;
}
}
// In your code
var comparer = new FooEqualityComparer();
var itemsToRemove = oldList.Except(newList, comparer );
var itemsToAdd = newList.Except(oldList, comparer);
公共类FooEqualityComparer:IEqualityComparer
{
公共布尔等于(左,右)
{
if(left==null&&right==null)返回true;
返回left!=null&&right!=null&&left.Bar==right.Bar;
}
public int GetHashCode(Foo项)
{
返回项!=null?item.Bar.GetHashcode():0;
}
}
//在代码中
var comparer=new FooEqualityComparer();
var itemsToRemove=oldList.Except(newList,comparer);
var itemsToAdd=newList.Except(oldList,comparer);
您的逻辑是正确的,但是比较两个类的默认行为是按引用进行。由于您可以有效地创建两个包含8个不同对象(无论其内容如何)的列表,因此不会有两个相等的对象
但是,您可以使用。例如:
public class FooEqualityComparer : IEqualityComparer<Foo>
{
public bool Equals(Foo left, Foo right)
{
if(left == null && right == null) return true;
return left != null && right != null && left.Bar == right.Bar;
}
public int GetHashCode(Foo item)
{
return item != null ? item.Bar.GetHashcode() : 0;
}
}
// In your code
var comparer = new FooEqualityComparer();
var itemsToRemove = oldList.Except(newList, comparer );
var itemsToAdd = newList.Except(oldList, comparer);
公共类FooEqualityComparer:IEqualityComparer
{
公共布尔等于(左,右)
{
if(left==null&&right==null)返回true;
返回left!=null&&right!=null&&left.Bar==right.Bar;
}
public int GetHashCode(Foo项)
{
返回项!=null?item.Bar.GetHashcode():0;
}
}
//在代码中
var comparer=new FooEqualityComparer();
var itemsToRemove=oldList.Except(newList,comparer);
var itemsToAdd=newList.Except(oldList,comparer);
在数据对象上实现IComparable;我想你被参照物的比较给咬了。如果您将Foo更改为string,则代码可以正常工作
var oldList = new List<string>();
oldList.Add("bar one");
oldList.Add("bar two");
oldList.Add("bar three");
oldList.Add("bar four");
var newList = new List<string>();
newList.Add("bar two");
newList.Add("bar three");
newList.Add("bar four");
newList.Add("bar five");
var itemsToRemove = oldList.Except(newList); // should only contain "bar one"
var itemsToAdd = newList.Except(oldList); // should only contain "bar one"
foreach (var item in itemsToRemove)
{
Console.WriteLine(item + " removed");
}
foreach (var item in itemsToAdd)
{
Console.WriteLine(item + " added");
}
var oldList=新列表();
添加(“第一栏”);
添加(“第二栏”);
添加(“第三栏”);
添加(“第四栏”);
var newList=新列表();
新增列表。添加(“第二栏”);
新增列表。添加(“第三栏”);
新增列表。添加(“第四栏”);
新增列表。添加(“第五栏”);
var itemsToRemove=oldList.Except(newList);//应仅包含“第一栏”
var itemsToAdd=newList.Except(oldList);//应仅包含“第一栏”
foreach(itemsToRemove中的变量项)
{
控制台写入线(项目+“删除”);
}
foreach(itemsToAdd中的var项)
{
控制台写入线(项目+“添加”);
}
在数据对象上实现IComparable;我想你被参照物的比较给咬了。如果您将Foo更改为string,则代码可以正常工作
var oldList = new List<string>();
oldList.Add("bar one");
oldList.Add("bar two");
oldList.Add("bar three");
oldList.Add("bar four");
var newList = new List<string>();
newList.Add("bar two");
newList.Add("bar three");
newList.Add("bar four");
newList.Add("bar five");
var itemsToRemove = oldList.Except(newList); // should only contain "bar one"
var itemsToAdd = newList.Except(oldList); // should only contain "bar one"
foreach (var item in itemsToRemove)
{
Console.WriteLine(item + " removed");
}
foreach (var item in itemsToAdd)
{
Console.WriteLine(item + " added");
}
var oldList=新列表();
添加(“第一栏”);
添加(“第二栏”);
添加(“第三栏”);
添加(“第四栏”);
var newList=新列表();
新增列表。添加(“第二栏”);
新增列表。添加(“第三栏”);
新增列表。添加(“第四栏”);
新增列表。添加(“第五栏”);
var itemsToRemove=oldList.Except(newList);//应仅包含“第一栏”
var itemsToAdd=newList.Except(oldList);//应仅包含“第一栏”
foreach(itemsToRemove中的变量项)
{
控制台写入线(项目+“删除”);
}
foreach(itemsToAdd中的var项)
{
控制台写入线(项目+“添加”);
}
这主要是一段关于