Equality for 2 lists of different types

Suppose we have 2 collections, at least IEnumerable to include Linq (also assume .net 4.0):

List<T1> list1; List<T2> list2; 

I can define equality between objects of type T1 and T2.

  • What is the best way (e.g. .net and Linq interface) to check if 2 lists are equal (the order of the elements doesn't matter).

  • How can I optimize this problem if I know that objects T1 and T2 have an identifier

Ex of T1 and T2:

 class Device { string Id; string Name; } class DeviceInfo { string Identifier; string FriendlyName; DateTime CreateDate; } 

Next edit:

The solution should be some kind of comparative comparison, which I write and is fairly general. There may be cases when 2 objects have the same name but a different name, and then the comparison is not performed. For instance:

 static bool AreEqual(Device device, DeviceInfo deviceInfo) { return device.Id == deviceInfo.Identifier && device.Name == deviceInfo.FriendlyName; } 
+4
source share
4 answers

Assuming .NET 4.0:

 Foo[] foos = new Foo[]; Bar[] bars = new Bar[]; var areDifferent = foos.Zip(bars, (foo, bar) => foo.Id == bar.Id).Any(b => !b); 

A better solution would also check that foos and bars are the same length and that none of the elements are null . And, of course, in this example, it is assumed that the collections are already sorted by Id .

Update:

So here is the “best solution” in all of its LINQy details:

 var areDifferent = foos.Count() != bars.Count() || foos.OrderBy(foo => foo.Id) .Zip( bars.OrderBy(bar => bar.Id), (foo, bar) => foo != null && bar != null && foo.Id == bar.Id) .Any(b => !b); 
+3
source

You can do something like this:

 List<Device> devices = ... List<DeviceInfo> deviceInfos = ... var deviceIds = devices.Select(d => d.Id) .OrderBy(id => id); var deviceInfoIds = deviceInfos.Select(d => d.Identifier) .OrderBy(id => id); bool areEqual = deviceIds.SequenceEqual(deviceInfoIds); 

If duplicate identifiers are not possible, specify the semantics:

 bool areEqual = !devices.Select(d => d.Id) .Except(deviceInfos.Select(d => d.Identifier)) .Any(); 

I would recommend, if possible, that you declare an IHasId interface (or similar) and get both types to implement it.

EDIT

In response to your editing, you can write an implementation of IEqualityComparer that did what you wanted. It would look very ugly; you will need to make a speculative selection from each argument in DeviceInfo / Device in order to try to extract the identifier. I would not recommend this; it is a bad idea to compare equality to compare objects of completely different types. It would be much simpler if each type implements a common interface that provides an identifier.

+2
source

Comparing two line lists is not very difficult. Both list-based solutions have a complexity of N log (N), not considering line size. Best solution (pseudo-code), complexity - N:

 create a dictionary<string, int> foreach element in list1 if element is in dict dict[element]++; else dict[element] = 1; foreach element in list2 if element is in dict dict[element]--; else return NOT_EQUAL; if dict has only 0 values lists are equal 
0
source

Try this to get the difference between two different lists: If they have a common property.

  var differentItems = List<Type1>.Select(d => d.Name) .Except(List<Type2>.Select(d => d.Name)); 
0
source

Source: https://habr.com/ru/post/1334205/


All Articles