C# 从Ienumerable.except获取精确的差值

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

我正在使用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",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)的内容。无法将类型为“WhereEnumerableTerator
1[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);
    }