同步2个列表

时间:2013-04-30 15:15:41

标签: c# .net-3.5

同步2个列表的最快方法是什么?

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>();

每个小组的成员数量不同。 我怎样才能找到不同的并将它们合并到一个新列表中?

PS:我可以将类型从IList更改为任何更高效的类型。

由于

5 个答案:

答案 0 :(得分:6)

首先,我们需要一种比较这些对象的有效方法。由于默认的EqualsGetHashCode实现在您的上下文中没有用,您需要覆盖它们,或创建IEqualityComparer。我做了后者,如果你愿意,你可以随意做前者。这是一个简单的比较器:

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();
    }
}

现在您已拥有此比较器,您可以利用LINQ为您完成工作:

var combinedList = userGroup1.Union(userGroup2, new UserGroupComparer())
    .ToList();

这将包含列表中的所有用户组,但没有任何重复项。

答案 1 :(得分:1)

您可以尝试:

userGroup1.Concat(userGroup2).Distinct();

不要忘记为UserGroup类重写Equals和GetHashCode。

答案 2 :(得分:0)

请参阅此问题的答案:Create a list from two object lists with linq

基本上你可以在System.Linq

中使用它

userGroup1.Union(userGroup2).ToList();

答案 3 :(得分:0)

您可以使用HashSet,请参阅以下链接类http://msdn.microsoft.com/en-us/library/bb383091.aspx

答案 4 :(得分:0)

如果集合中的项目属于两种不同类型,则可以使用以下内容:

 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);
                }
            }
        }
    }

用法如下:

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);