Reputation: 7193
I have a
ObservableCollection<BasicClass> allCollection;
ObservableCollection<BasicClass> selectedCollection;
where
BasicClass
{
public Name {get;set;}
public Age {get;set;}
}
Now I added many BasicClass
items to allCollection
and only selected BasicClass
to selectedCollection
SomeWhere I want to add items in selectedCollection
which are not there in allCollection
.
I tried this
foreach(var a in allCollection)
{
foreach(var s in selectedCollection)
if(a.Name!=s.Name)
//selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age});
}
But the problem is that this code is adding new BasicClass for each and every unmatched name, but my actuall requirement is, for each Name of allCollection compare all selectedCollection items. If it is not there then add else move for next Item.
LINQ solution could help this? Actually I achieved this by more if and flags but That looks ver hectic. My traditional solution
foreach(var a in allCollection)
{
bool same = false;
foreach(var s in selectedCollection)
if(a.Name==s.Name)
same=true;
}
if(same==false)
selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age});
And I hate this..
EDIT:
I don't want compare collection to collection. I want to compare collection1 value to collection2 all values, and if it not there then I want to add
Upvotes: 1
Views: 617
Reputation: 8511
Are you sure you don't just need this?
foreach(var a in allCollection)
{
if (!selectedCollection.Contains(a))
selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age});
}
EDIT
I've just seen your comment below about matching on name only, so the above is not really what you want:). Try this approach instead:
foreach(var a in allCollection)
{
if (!selectedCollection.Any(s => a.Name == s.Name))
{
selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age});
}
}
EDIT
As Chris suggested you could also use "Except" to create a collection. I'm not sure this gains much, it may be quicker but it involves writing the comparer code and creates a new temporary collection. However, it is pretty succinct E.g. Once you had the comparaer written you would just need this to add your missing items to the collection:
selectedCollection.Concat(allCollection.Except(selectedCollection));
Upvotes: 1
Reputation: 292465
I'm not sure I understood your requirements correctly, so i may be missing the point...
Your BasicClass
should implement the IEquatable<BasicClass>
interface, so that two instances of BasicClass
can be compared for equality:
class BasicClass : IEquatable<BasicClass>
{
public Name {get;set;}
public Age {get;set;}
public bool Equals(BasicClass other)
{
if (other == null)
return false;
return string.Equals(this.Name, other.Name);
}
public override int GetHashCode()
{
return Name == null ? 0 : Name.GetHashCode();
}
}
Now you can use the Except
method to find items that are in allCollection
but not in selectedCollection
:
BasicClass[] notSelected = allCollection.Except(selectedCollection).ToArray();
foreach(BasicClass item in notSelected)
{
selectedCollection.Add(item);
}
Alternatively, you can implement a IEqualityComparer<BasicClass>
and pass it to Except
(instead of implementing IEquatable<BasicClass>
in BasicClass
)
Upvotes: 1
Reputation: 3136
So basically you need a 'where-not-in'? Linq->Except is the way to go, to filter on BasicClass.name only implement the IEqualityComparer for Except.
Upvotes: 1
Reputation: 13104
You're right, this is more easily accomplished with Linq:
var itemsToAdd = allCollection.Except(selectedCollection);
foreach (var item in itemsToAdd)
selectedCollection.Add(item);
On the other hand, this is just going to make both lists contain the exact same items. Sure this is what you want?
If BasicItem overrides 'Equals' and 'GetHashCode' based off of Name, then this is all you need. If it doesn't, then you will also need to implement an IEqualityComparer:
//Allows us to compare BasicItems as if Name is the key
class NameComparer: IEqualityComparer<BasicItem>
{
public bool Equals(BasicItem first, BasicItem second)
{
return first.Name == second.Name;
}
public int GetHashCode(BasicItem value)
{
return value.Name.GetHashCode;
}
}
You now pass an instance of this class to Except
:
var itemsToAdd = allCollections.Except(selectedCollection, new NameComparer());
Upvotes: 0