C# 从Ienumerable.except获取精确的差值
我正在使用LINQ ENumerable.except从两个MyType列表中获取差异。当我找到一个diff时,我需要检索相应diff项的base和compare列表中的不同之处。像 我有两份清单要比较C# 从Ienumerable.except获取精确的差值,c#,linq,C#,Linq,我正在使用LINQ ENumerable.except从两个MyType列表中获取差异。当我找到一个diff时,我需要检索相应diff项的base和compare列表中的不同之处。像 我有两份清单要比较 Base: Name="1",Type="a",Switch="384347324372432" Name="1",Type="b",Switch="43432432423" Name="2",Type="q",Switch="4324324234" Compare List: Name="1
Base:
Name="1",Type="a",Switch="384347324372432"
Name="1",Type="b",Switch="43432432423"
Name="2",Type="q",Switch="4324324234"
Compare List:
Name="1",Type="a",Switch="aAAAA384347324372432"
Name="1",Type="c",Switch="23432432"
Name="2",Type="q",Switch="3423432423432"
Name="2",Type="q",Switch="4324324234"
乌普特是
Found diff.
Base:
Name="1",Type="a",Switch="384347324372432"
Corresponding compare value:
Name="1",Type="a",Switch="aAAAA384347324372432"
etc...
我已经编写了自己的类对象,比如MyType,用于将这些项存储为属性
定义了一个自定义比较器,如
class mycomparer: System.Collections.Generic.IEqualityComparer<MyType>
{
public mycomparer() {}
public bool Equals(MyType type1, MyType type2)
{
return ( (type1.Name.ToLower() == type2.Name.ToLower()) && (type1.Type.ToLower() == type2.Type.ToLower()) (type1.Switch.ToLower() == type2.Switch.ToLower())
}
public int GetHashCode(MyType type)
{
return string.concat(type.Name, type.Type, type.Switch).ToLower().GetHashCode();
}
}
如何获取比较列表的相应值
我试过这样的方法
IEnumerable<MyType> compareValue = Comparelist.Where(tempFile => tempFile.Name.ToLower() == type.Name.ToLower() && tempFile.Type.ToLower() == process.Type.ToLower()
但是
diffSwitches.ToList().ForEach
我会得到类似的东西
base: Name="2",Type="q",Switch="3423432423432"
Compare: Name="2",Type="q",Switch="4324324234"
您可以看到,这不是相应的不匹配。事实开关=“4324324234”已正确匹配。这就是我看到的问题
谢谢。试试这个
baseList.Except( compareList, mine ).Union( compareList.Except( baseList.Except, mine ) )
在新要求后编辑:
var baseList = new List<MyType>()
{
new MyType() { Name="1",Type="a",Switch="384347324372432" },
new MyType() { Name="1",Type="b",Switch="43432432423" },
new MyType() { Name="2",Type="q",Switch="4324324234" }
};
var compareList = new List<MyType>()
{
new MyType() { Name="1",Type="a",Switch="aAAAA384347324372432" },
new MyType() { Name="1",Type="c",Switch="23432432" },
new MyType() { Name="2",Type="q",Switch="3423432423432" },
new MyType() { Name="2",Type="q",Switch="4324324234" }
};
// matched Name/Type w/ different Switch
var diffSwitches = baseList.Join( compareList,
bl => new { bl.Name, bl.Type },
cl => new { cl.Name, cl.Type },
( bl, cl ) => new {
baseItem = bl,
compareItem = cl } )
.Where( o => o.baseItem.Switch != o.compareItem.Switch );
diffSwitches.ToList().ForEach(i => Console.WriteLine("{0}-{1}: {2}; {3}", i.baseItem.Name, i.baseItem.Type, i.baseItem.Switch, i.compareItem.Switch));
var baseList=新列表()
{
新建MyType(){Name=“1”,Type=“a”,Switch=“384347324372432”},
新建MyType(){Name=“1”,Type=“b”,Switch=“432432423”},
新建MyType(){Name=“2”,Type=“q”,Switch=“4324324234”}
};
var compareList=新列表()
{
新建MyType(){Name=“1”,Type=“a”,Switch=“aaaaa3843347324372432”},
新建MyType(){Name=“1”,Type=“c”,Switch=“2343432”},
新建MyType(){Name=“2”,Type=“q”,Switch=“3423432”},
新建MyType(){Name=“2”,Type=“q”,Switch=“4324324234”}
};
//匹配的名称/类型与不同的开关
var diffSwitches=baseList.Join(compareList,
bl=>新的{bl.Name,bl.Type},
cl=>新的{cl.Name,cl.Type},
(bl,cl)=>新{
基本项=bl,
compareItem=cl})
.其中(o=>o.baseItem.Switch!=o.compareItem.Switch);
ForEach(i=>Console.WriteLine(“{0}-{1}:{2};{3}”,i.baseItem.Name,i.baseItem.Type,i.baseItem.Switch,i.compareItem.Switch));
将两个列表命名为list
和list2
。这是一个解决方案:
var common = list1.Intersect(list2, new mycomparer());
var result = list1.Concat(list2)
.Except(common, new mycomparer())
.GroupBy (x => new { x.Name, x.Type } );
因此,两个列表都被连接起来,然后两个列表中的公共元素被删除,最后剩下的项目按Name
和Type
进行分组
如果
MyType
是一个struct
,您不需要比较器,因为当结构的值相等时,它们是相等的。我想您只需稍微更改比较器,就可以得到想要的结果:
class mycomparer : System.Collections.Generic.IEqualityComparer<Item>
{
bool customcomparer = false;
public mycomparer(bool custom = false)
{
customcomparer = custom;
}
public bool Equals(Item type1, Item type2)
{
return GetHashCode(type1) == GetHashCode(type2);
}
public int GetHashCode(Item type)
{
if (customcomparer)
return string.Concat(type.Name, type.Type).ToLower().GetHashCode();
return string.Concat(type.Name, type.Type, type.Switch).ToLower().GetHashCode();
}
}
第二个数字是这样的:
public class MyType
{
public String Name, Type, Switch;
public MyType()
{
}
public MyType(string _name, string _type, string _switch)
{
Name = _name;
Type = _type;
Switch = _switch;
}
public override string ToString()
{
return "Name = " + this.Name + ",Type = " + this.Type + ",Switch = " + this.Switch;
}
}
private void button3_Click(object sender, EventArgs e)
{
mycomparer mine = new mycomparer();
mycomparer mine2 = new mycomparer(true);
IEnumerable<MyType> diff = baseList.Except(compareList, mine);
IEnumerable<MyType> diff2 = compareList.Intersect(diff, mine2);
string message = "Base:\n";
foreach (MyType item in diff)
{
message += item.ToString() + "\n";
}
message += "Corresponding compare value:\n";
foreach (MyType item in diff2)
{
message += item.ToString() + "\n";
}
MessageBox.Show(message);
}
private void按钮3\u单击(对象发送者,事件参数e)
{
mycomparer mine=新的mycomparer();
mycomparer mine2=新的mycomparer(真);
IEnumerable diff=基本列表。除了(比较列表,我的);
IEnumerable diff2=比较列表相交(diff,mine2);
string message=“基:\n”;
foreach(差异中的MyType项目)
{
message+=item.ToString()+“\n”;
}
消息+=“对应的比较值:\n”;
foreach(diff2中的MyType项)
{
message+=item.ToString()+“\n”;
}
MessageBox.Show(message);
}
我注意到
diff
返回两个项目,分别为1个类型a和1个类型b。这是您的原始代码,因此我将其保留为那样。这将列出两个列表中的所有差异,但我仍然无法说出相应的不匹配是什么。联接操作的返回时间是多少?我收到关于无法强制转换为类型的运行时错误。我还将b1=>new{}更新为类似b1=>newmytype(name,type)的内容。无法将类型为“WhereEnumerableTerator1[f_uAnonymousType0
2[MyType,MyType]]”的对象强制转换为类型为“System.Collections.Generic.IEnumerable`1[MyType]”。返回类型是具有baseItem和compareItem属性的匿名类型谢谢。这似乎正确地简化了我的代码,但看起来我遇到了与撰写本文相同的问题。当有多个name=和type=时。请看文章的结尾。问题是我想把相应的条目写在一起。我希望能够在我的日志中比较它们。对不起,这不是我要找的。我需要两个列表之间的对应差异。这个“对应差异”的概念仍然令人困惑。这是一个矛盾的术语。要么元素不同,要么它们对应。您似乎通过名称和类型的共同性来定义通信。我的查询在概念上是错误的,还是仅仅是输出的形状不符合要求?
class mycomparer : System.Collections.Generic.IEqualityComparer<Item>
{
bool customcomparer = false;
public mycomparer(bool custom = false)
{
customcomparer = custom;
}
public bool Equals(Item type1, Item type2)
{
return GetHashCode(type1) == GetHashCode(type2);
}
public int GetHashCode(Item type)
{
if (customcomparer)
return string.Concat(type.Name, type.Type).ToLower().GetHashCode();
return string.Concat(type.Name, type.Type, type.Switch).ToLower().GetHashCode();
}
}
public class MyType
{
public String Name, Type, Switch;
public MyType()
{
}
public MyType(string _name, string _type, string _switch)
{
Name = _name;
Type = _type;
Switch = _switch;
}
public override string ToString()
{
return "Name = " + this.Name + ",Type = " + this.Type + ",Switch = " + this.Switch;
}
}
private void button3_Click(object sender, EventArgs e)
{
mycomparer mine = new mycomparer();
mycomparer mine2 = new mycomparer(true);
IEnumerable<MyType> diff = baseList.Except(compareList, mine);
IEnumerable<MyType> diff2 = compareList.Intersect(diff, mine2);
string message = "Base:\n";
foreach (MyType item in diff)
{
message += item.ToString() + "\n";
}
message += "Corresponding compare value:\n";
foreach (MyType item in diff2)
{
message += item.ToString() + "\n";
}
MessageBox.Show(message);
}