C#: Compare contents of two IEnumerables
There are quite a few ways. Assume A and B is IEnumerable.
!A.Except(B).Any() && !B.Except(A).Any()
A.Count() == B.Count() && A.Intersect(B).Count() == B.Count()
etc
What is the shortest way to compare if two IEnumerable<T> have the same items in C#?
Even if the order doesn't matter to you, it doesn't rule out SequenceEqual as a viable option.
var lst1 = new [] { 2,2,2,2 };
var lst2 = new [] { 2,3,4,5 };
var lst3 = new [] { 5,4,3,2 };
//your current function which will return true
//when you compare lst1 and lst2, even though
//lst1 is just a subset of lst2 and is not actually equal
//as mentioned by Wim Coenen
(lst1.Count() == lst2.Count() &&
!lst1.Except(lst2).Any()); //incorrectly returns true
//this also only checks to see if one list is a subset of another
//also mentioned by Wim Coenen
lst1.Intersect(lst2).Any(); //incorrectly returns true
//So even if order doesn't matter, you can make it matter just for
//the equality check like so:
lst1.OrderBy(x => x).SequenceEqual(lst2.OrderBy(x => x)); //correctly returns false
lst3.OrderBy(x => x).SequenceEqual(lst2.OrderBy(x => x)); // correctly returns true
Most efficient way to compare two generic lists based on id elements contained within nested list (C#)
Your current algorithm seem to be O(n*m*s*s)
where n = number of existing items, m = number number of potential matches and s = average number of suppliers for each existingItem/PotentialMatch. You could reduce the running time to O(n*m*s)
by using a hash-set for the matching of suppliers.
A generic version would look like this
public static IEnumerable<(T1, T2)> SetJoin<T1, T2, TKey>(
IEnumerable<T1> t1s,
IEnumerable<T2> t2s,
Func<T1, IEnumerable<TKey>> t1Key,
Func<T2, IEnumerable<TKey>> t2Key) where TKey : IEquatable<TKey>
{
foreach (var t1 in t1s)
{
var t1Keys = new HashSet<TKey>(t1Key(t1));
foreach (var t2 in t2s)
{
// t2Key(t2) would be called many times,
// might be worth pre-computing it for each t2.
if (t2Key(t2).Any(t1Keys.Contains))
{
yield return (t1, t2);
}
}
}
}
And call it like
SetJoin<ExistingItems, PotentialMatches, int>(
existingItems,
potentialMatches,
e=> e.Suppliers.Select(s => s.Id),
p => p.Suppliers.Select(s => s.Id))
Also, while linq result in compact and nice code, it is often faster to write the equivalent logic using regular loops if performance is important.
Better way of comparing two lists with LINQ?
I would do this:
var map = allElements.ToDictionary(x => x.Id);
if (!someElements.All(id => map.ContainsKey(id))
{
// Return early
}
var list = someElements.Select(x => map[x])
.ToList();
Note that the first line will throw an exception if there are any duplicates in allElements
.
How to compare two lists and change one property
Given that your target list is named targetDocs
and the list you want to check for document existance is srcDocs
try something like (don't have access to a compiler here so can't test):
targetDocs.ForEach(d => d.IsActive = srcDocs.Any(sd => sd.id == d.Id))
I'm assuming that we are talking about List
s and not other collection types as the ForEach extension method is defined for List
s.
LINQ (or something else) to compare a pair of values from two lists (in any order)?
You can do in this way:
Define a custom IEqualityComparer<FooAttribute>
:
class FooAttributeComparer : IEqualityComparer<FooAttribute>
{
public bool Equals(FooAttribute x, FooAttribute y)
{
return x.Match(y);
}
public int GetHashCode(FooAttribute obj)
{
return 0;
// This makes lookups complexity O(n) but it could be reasonable for small lists
// or if you're not sure about GetHashCode() implementation to do.
// If you want more speed you could return e.g. :
// return obj.Field1.GetHashCode() ^ (17 * obj.Field2.GetHashCode());
}
}
Define an extension method to compare lists in any order and having the same number of equal elements:
public static bool ListContentIsEqualInAnyOrder<T>(
this IEnumerable<T> list1, IEnumerable<T> list2, IEqualityComparer<T> comparer)
{
var lookup1 = list1.ToLookup(x => x, comparer);
var lookup2 = list2.ToLookup(x => x, comparer);
if (lookup1.Count != lookup2.Count)
return false;
return lookup1.All(el1 => lookup2.Contains(el1.Key) &&
lookup2[el1.Key].Count() == el1.Count());
}
Usage example:
static void Main(string[] args)
{
List<FooAttribute> attrs = new List<FooAttribute>
{
new FooAttribute(typeof(int), typeof(double)),
new FooAttribute(typeof(int), typeof(double)),
new FooAttribute(typeof(bool), typeof(float)),
new FooAttribute(typeof(uint), typeof(string)),
};
List<FooAttribute> attrs2 = new List<FooAttribute>
{
new FooAttribute(typeof(uint), typeof(string)),
new FooAttribute(typeof(int), typeof(double)),
new FooAttribute(typeof(int), typeof(double)),
new FooAttribute(typeof(bool), typeof(float)),
};
// this returns true
var listEqual1 = attrs.ListContentIsEqualInAnyOrder(attrs2, new FooAttributeComparer());
// this returns false
attrs2.RemoveAt(1);
var listEqual2 = attrs.ListContentIsEqualInAnyOrder(attrs2, new FooAttributeComparer());
}
Related Topics
Updating an Object from a List in C#
Merge Multiple Lists into One List With Linq
How to Delete Records Between Two Dates in Bulk
Encode a Filestream to Base64 With C#
How to Read Appsettings.Json With Array of Values
What Regular Expression Would I Use to Remove Everything After the Second Backslash
Use Linq to Collaps Multiply Collections into One Collection
Model Id Property Null in ASP.NET MVC C#
Download File from an ASP.NET Web API Method Using Angularjs
Programmatically Create and Launch and Rdp Session (Without Gui)
How to Convert Any Date Format to Yyyy-Mm-Dd
Fastest Way to Find Strings in a File
How to Convert a List to Ienumerable
How to Check Byte Array Empty or Not
Clearing a Textbox Leaves an Invisible Character
How to Loop Through All Fields in an Object in C#
How to Get Cookies Info Inside of a Cookiecontainer (All of Them, Not for a Specific Domain)