Reputation: 2629
What is the best fastest way to Synchronize 2 Lists?
public class UserGroup
{
public UserGroup(string group, string user)
{
this.Group = group;
this.User = user;
}
public string Group { get; set; }
public string User { get; set; }
}
IList<UserGroup> userGroup1 = new IList<UserGroup>();
IList<UserGroup> userGroup2 = new IList<UserGroup>();
Each group has different number of members. How can i find out the different and merge both in one new list?
PS: I can change the type from IList to whatever if it would be more efficient.
Thanks
Upvotes: 2
Views: 11088
Reputation: 89
The following could be used if the items in collections are of two different types:
class CollectionSynchronizer<TSource, TDestination>
{
public Func<TSource, TDestination, bool> CompareFunc { get; set; }
public Action<TDestination> RemoveAction { get; set; }
public Action<TSource> AddAction { get; set; }
public Action<TSource, TDestination> UpdateAction { get; set; }
public void Synchronizer(ICollection<TSource> sourceItems, ICollection<TDestination> destinationItems)
{
// Remove items not in source from destination
RemoveItems(sourceItems, destinationItems);
// Add items in source to destination
AddOrUpdateItems(sourceItems, destinationItems);
}
private void RemoveItems(ICollection<TSource> sourceCollection, ICollection<TDestination> destinationCollection)
{
foreach (var destinationItem in destinationCollection.ToArray())
{
var sourceItem = sourceCollection.FirstOrDefault(item => CompareFunc(item, destinationItem));
if (sourceItem == null)
{
RemoveAction(destinationItem);
}
}
}
private void AddOrUpdateItems(ICollection<TSource> sourceCollection, ICollection<TDestination> destinationCollection)
{
var destinationList = destinationCollection.ToList();
foreach (var sourceItem in sourceCollection)
{
var destinationItem = destinationList.FirstOrDefault(item => CompareFunc(sourceItem, item));
if (destinationItem == null)
{
AddAction(sourceItem);
}
else
{
UpdateAction(sourceItem, destinationItem);
}
}
}
}
And the usage would be like this:
var collectionSynchronizer = new CollectionSynchronizer<string, ContentImageEntity>
{
CompareFunc = (communityImage, contentImage) => communityImage == contentImage.Name,
AddAction = sourceItem =>
{
var contentEntityImage = _contentImageProvider.Create(sourceItem);
contentEntityImages.Add(contentEntityImage);
},
UpdateAction = (communityImage, contentImage) =>
{
_contentImageProvider.Update(contentImage);
},
RemoveAction = contentImage =>
{
contentEntityImages.Remove(contentImage);
}
};
collectionSynchronizer.Synchronizer(externalContentImages, contentEntityImages);
Upvotes: 1
Reputation: 203827
So first we need an effective way of comparing these objects. Since the default Equals
and GetHashCode
implementations won't be useful in your context you either need to override them, or create an IEqualityComparer
. I did the latter, you can feel free to do the former if you want. Here's a simple comparer:
public class UserGroupComparer : IEqualityComparer<UserGroup>
{
public bool Equals(UserGroup x, UserGroup y)
{
return x.Group == y.Group && x.User == y.User;
}
public int GetHashCode(UserGroup obj)
{
return 37 * obj.Group.GetHashCode() + 19 * obj.User.GetHashCode();
}
}
Now that you have this comparer you can leverage LINQ to do the work for you:
var combinedList = userGroup1.Union(userGroup2, new UserGroupComparer())
.ToList();
That will have all of the user groups that are in either list, but without any duplicates.
Upvotes: 7
Reputation: 550
You may use HashSet see following link class http://msdn.microsoft.com/en-us/library/bb383091.aspx
Upvotes: 0
Reputation: 7619
See the answer to this question: Create a list from two object lists with linq
Basically you can use this in System.Linq
:
userGroup1.Union(userGroup2).ToList();
Upvotes: 0
Reputation: 12654
You can try:
userGroup1.Concat(userGroup2).Distinct();
And don't forget to override Equals and GetHashCode for UserGroup class.
Upvotes: 1