代码之家  ›  专栏  ›  技术社区  ›  Ganesha

C一般列表联合问题

  •  8
  • Ganesha  · 技术社区  · 16 年前

    我正在尝试使用“union”合并两个列表,以便消除重复项。以下是示例代码:

    public class SomeDetail
    {
        public string SomeValue1 { get; set; }
        public string SomeValue2  { get; set; }
        public string SomeDate { get; set; }
    }
    
    public class SomeDetailComparer : IEqualityComparer<SomeDetail>
    {
        bool IEqualityComparer<SomeDetail>.Equals(SomeDetail x, SomeDetail y)
        {
            // Check whether the compared objects reference the same data.        
            if (Object.ReferenceEquals(x, y))
                return true;
            // Check whether any of the compared objects is null.        
            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
                return false;
            return x.SomeValue1 == y.SomeValue1 && x.SomeValue2 == y.SomeValue2;
        }
        int IEqualityComparer<SomeDetail>.GetHashCode(SomeDetail obj)
        {
            return obj.SomeValue1.GetHashCode();
        }
    }
    
    List<SomeDetail> tempList1 = new List<SomeDetail>();
    List<SomeDetail> tempList2 = new List<SomeDetail>();
    
    List<SomeDetail> detailList = tempList1.Union(tempList2, SomeDetailComparer).ToList();
    

    现在的问题是,我是否可以使用union并仍然获取具有最新日期的记录(使用somedate属性)。记录本身可以在templist1或templist2中。

    提前谢谢

    6 回复  |  直到 10 年前
        1
  •  8
  •   Noldorin    16 年前

    真正适合此目的的操作是 full outer join . 这个 Enumerable 类具有内部联接的实现,您可以使用该实现查找重复项并选择您喜欢的内容。

    var duplicates = Enumerable.Join(tempList1, tempList2,  keySelector, keySelector, 
        (item1, item2) => (item1.SomeDate > item2.SomeDate) ? item1 : item2)
        .ToList();
    

    keySelector 只是从类型的对象中提取键的函数(可以是lambda表达式) SomeDetail . 现在,要实现完整的外部联接,请尝试如下操作:

    var keyComparer = (SomeDetail item) => new { Value1 = item.SomeValue1,
        Value2 = item.SomeDetail2 };
    var detailList = Enumerable.Union(tempList1.Except(tempList2, equalityComparer), 
        tempList2.Except(tempList1, equalityComparer)).Union(
        Enumerable.Join(tempList1, tempList2, keyComparer, keyComparer
        (item1, item2) => (item1.SomeDate > item2.SomeDate) ? item1 : item2))
        .ToList();
    

    equalityComparer 应该是实现 IEqualityComparer<SomeDetail> 并有效地利用 keyComparer 用于测试相等性的函数。

    如果这对你有帮助,请告诉我。

        2
  •  1
  •   John Weldon user3678248    16 年前

    你必须能够告诉工会如何选择要使用的副本。除了写你自己的工会,我不知道怎么做。

        3
  •  1
  •   Daniel Brückner    16 年前

    你不能用标准 Union 方法,但可以创建扩展方法 联合 对于 List<SomeDetail> 使用这种特殊的处理方法,将使用这种方法,因为签名更适合。

        4
  •  1
  •   Chris Doggett    16 年前

    为什么不使用hashset<t>?

    List<SomeDetail> tempList1 = new List<SomeDetail>();
    List<SomeDetail> tempList2 = new List<SomeDetail>();
    
    HashSet<SomeDetail> hs = new HashSet<SomeDetail>(new SomeDetailComparer());
    
    hs.UnionWith(tempList1);
    hs.UnionWith(tempList2);
    
    List<SomeDetail> detailList = hs.ToList();
    
        5
  •  0
  •   Michael D. Irizarry    15 年前

    合并通用列表

        public static List<T> MergeListCollections<T>(List<T> firstList, List<T> secondList)
        {
            List<T> merged = new List<T>(firstList);
            merged.AddRange(secondList);
            return merged;
        }
    
        6
  •  -1
  •   Adem Aygun    10 年前

    试试这个:

    list1.RemoveAll(p => list2.Any(z => z.SomeValue1 == p.SomeValue1 &&
                                   z => z.SomeValue2 == p.SomeValue1 &&
                                   z => z.SomeDate == p.SomeDate));
    var list3 =  list2.Concat<SomeDetail>(list1).ToList();