I am using LINQ ENumerable.except to get the diff out of two lists of MyType. When I find a diff, I need to retrieve what was different in both base and compare list for the corresponding diff item. LIke,
I have two lists to 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"
Ouuput would be
Found diff.
Base:
Name="1",Type="a",Switch="384347324372432"
Corresponding compare value:
Name="1",Type="a",Switch="aAAAA384347324372432"
etc...
I have written my own class object, say MyType for storing these as items properties
Defined a custom comparer like
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();
}
}
In my code, I use
MyComparer mine = new MyComparer();
IEnumerable<MyType> diff = baseList.Except(compareList,mine);
I get the diff correctly. But for the values that are different in baselist, I want to know what the corresponding value in comparelist was.
I do
foreach(Mytype type in diff)
{
Console.writeline(type.Name+type.Type+type.Switch);
}
How to I get the corresponding values for compare list.
I tried something like,
IEnumerable<MyType> compareValue = Comparelist.Where(tempFile => tempFile.Name.ToLower() == type.Name.ToLower() && tempFile.Type.ToLower() == process.Type.ToLower()
(Basically, switch is what could be different here mostly)
But the problem is, in some cases, there may be duplicate Name="" Type="", so the above where retrieves more than one item, so the corresponding comparelist value would be different.
I tried writing the diff values from Equal methods, but didnt work for me.
UPdate:
In the case when duplicate name and type are found and switch has a mismatch, I think diff is calculated correctly, but when the output is written to console, incorrect diff value is written, here is the sample.
Base:
Name="2",Type="q",Switch="4324324234"
Name="2",Type="q",Switch="3423432423432"
Compare List:
Name="2",Type="q",Switch="4324324234"
Name="2",Type="q",Switch="3423432423432dwqdwqdwqdqwdwdq"
base.except(compare) (as used in my sample code or Moho's solution) gets the diff correctly,
but with diffSwitches.ToList().ForEach
I will get something like
base: Name="2",Type="q",Switch="3423432423432"
Compare: Name="2",Type="q",Switch="4324324234"
You see that is not the corresponding mismatch. Infact Switch="4324324234" is correctly matched. This is the problem I see.
Thanks.
Try this
baseList.Except( compareList, mine ).Union( compareList.Except( baseList.Except, mine ) )
Edit after new requirements:
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));
Let both list be named list
and list2
. This is a solution:
var common = list1.Intersect(list2, new mycomparer());
var result = list1.Concat(list2)
.Except(common, new mycomparer())
.GroupBy (x => new { x.Name, x.Type } );
So both lists are concatenated, then the elements common in both lists are removed, and finally the remaining items are grouped by Name
and Type
.
Maybe useful to add that if MyType
is a struct
, you don't need the comparer, because structs are equal when their values are equal.
I think you can get the results you want with a slight change to your comparer:
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();
}
}
And your class set up like this:
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;
}
}
And a second IEnumerable like this:
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);
}
I noticed diff
returns 2 items Name 1 Type a and Name 1 Type b. This is from your original code so I left it like that.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.