Reputation: 18545
I have
List<List<string>> source
which contains for example
{{"a","b"},{"c","d"}}
I also have a
List<List<string>> target
which contains for example
{{"a","b"},{"e","f"}}
What is the easiest way I could get the List<string>
in source
that cannot be found in target
, be included in the target
?
Here {"c","d"}
can be found in source
but not target
, therefore after assignment the target
should be
{{"a","b"},{"e","f"},{"c","d"}}
Upvotes: 1
Views: 94
Reputation: 13022
Use Linq.Union
with custom comparer:
target = target.Union(source, new MyListComparer()) // Use the custom comparer to avoid duplication of the equal sequences.
.ToList();
With the equality comparer (if you want to have order independant comparison use the second choice in the Equals
function):
public class MyListComparer : IEqualityComparer<List<string>>
{
public bool Equals(List<string> x, List<string> y)
{
return x.SequenceEqual(y); // Use this if { "a", "b" } != { "a", "b" }
//return x.Count == y.Count && x.Count == x.Intersect(y).Count(); // Use this if { "a", "b" } == { "a", "b" }
}
public int GetHashCode(List<string> obj)
{
// GetHashCode is used to make the comparison faster by not comparing two elements that does not have the same hash code.
// GetHashCode must satisfy the following condition
// (x == y) implies (GetHashCode(x) == GetHashCode(y))
// If your are extremely lazy, you can always return 0 but then the complexity of Union will be quadratic instead of linear.
return obj.Sum(item => item.GetHashCode());
}
}
Upvotes: 3
Reputation: 16149
You could use LINQ:
target = source.Union(target).Distinct(new YourComparer()).ToList();
Then you would need to create a new class that inherits from IEqualityComparer (see here for an example of doing that) that would do the exact comparisons that you want.
Upvotes: 0