I am comparing 2 lists of objects using a custom comparer like so:
public class LocationEqualityComparer : IEqualityComparer<LocationData>
{
public bool Equals(LocationData x, LocationData y)
{
var idComparer = string.Equals(x.Id, y.Id,
System.StringComparison.OrdinalIgnoreCase);
var nameComparer = string.Equals(x.Name, y.Name,
System.StringComparison.OrdinalIgnoreCase);
var addressComparer = string.Equals(x.Address, y.Address,
System.StringComparison.OrdinalIgnoreCase);
var postcodeComparer = string.Equals(x.PostCode, y.PostCode,
System.StringComparison.OrdinalIgnoreCase);
if (idComparer && nameComparer && addressComparer && postcodeComparer)
{
return true;
}
return false;
}
}
This works great for me when using Linq to check the equality using:
If I have two lists of LocationData
(previousRun
and currentRun
, I get the correct result with:
List<LocationData> result = previousRun.Intersect(currentRun, new LocationEqualityComparer()).ToList();
I am also able to check which items have been added or deleted between the lists using Except
in Linq.
What I want to be able to do is check if an item has been UPDATED between the lists. This is because they represent an old list (previous run) and a new list (current run). So for example the LocationData object will have the same Id, same address and same postcode but might have a slightly different name.
Does anyone know how I can get a list of objects that have been updated between lists (i.e. only one or maybe two properties have changed) but not defined as added or deleted?
Thank you
You could simply write a method that does the property comparison, but which returns true
if a specific number of properties match (you said 1 or 2, so I guess it's variable?):
public static bool IsUpdated(LocationData previous, LocationData current,
int numPropsToMatch = 2)
{
// If they are equal, return false
if (new LocationEqualityComparer().Equals(previous, current)) return false;
int numMatchingProps = 0;
if (string.Equals(previous.Id, current.Id,
System.StringComparison.OrdinalIgnoreCase)) numMatchingProps++;
if (string.Equals(previous.Name, current.Name,
System.StringComparison.OrdinalIgnoreCase)) numMatchingProps++;
if (string.Equals(previous.Address, current.Address,
System.StringComparison.OrdinalIgnoreCase)) numMatchingProps++;
if (string.Equals(previous.PostCode, current.PostCode,
System.StringComparison.OrdinalIgnoreCase)) numMatchingProps++;
// Change to == if you *only* want a specific number to match
return numMatchingProps >= numPropsToMatch;
}
Then you can just use this method in your Linq statement:
List<LocationData> updated = currentRun
.Where(curr => previousRun.Any(prev => IsUpdated(prev, curr)))
.ToList();
Note that it's highly likely that more than one location will have the same postal code, so that should probably not be included, but since it wasn't specified I left it.