【问题标题】:Synchronize 2 lists同步 2 个列表
【发布时间】:2018-11-09 23:19:12
【问题描述】:

同步 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 更改为任何类型。

谢谢

【问题讨论】:

  • new IList&lt;UserGroup&gt;(); 不会编译。即使变量类型为IListnew 也需要使用正确的List
  • 您希望如何合并您的列表?结果应该包含第一个或第二个列表中存在的所有项目,还是只包含两个列表中存在的项目?

标签: c# .net-3.5


【解决方案1】:

所以首先我们需要一种有效的方法来比较这些对象。由于默认的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();

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

【讨论】:

    【解决方案2】:

    你可以试试:

    userGroup1.Concat(userGroup2).Distinct();
    

    不要忘记为 UserGroup 类覆盖 Equals 和 GetHashCode。

    【讨论】:

      【解决方案3】:

      查看此问题的答案:Create a list from two object lists with linq

      基本上你可以在System.Linq中使用它:

      userGroup1.Union(userGroup2).ToList();

      【讨论】:

      • 这将对类型使用引用相等...这可能是不可取的。
      【解决方案4】:

      你可以使用 HashSet 看下面的链接类http://msdn.microsoft.com/en-us/library/bb383091.aspx

      【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        猜你喜欢
        • 2011-04-26
        • 1970-01-01
        • 2013-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多