【问题标题】:Combining 2 lists and and remove duplicates .Output in a third list .My attempts do not work结合 2 个列表并删除重复项。在第三个列表中输出。我的尝试不起作用
【发布时间】:2010-09-10 05:32:58
【问题描述】:

当我需要比较 2 个列表并生成包含所有唯一项目的第三个列表时,我似乎总是遇到问题。我需要经常执行此操作。

尝试用一个点头的例子来重现这个问题。

我错过了什么吗? 感谢您的任何建议

想要的结果

   Name= Jo1 Surname= Bloggs1 Category= Account
   Name= Jo2 Surname= Bloggs2 Category= Sales
   Name= Jo5 Surname= Bloggs5 Category= Development
   Name= Jo6 Surname= Bloggs6 Category= Management
   Name= Jo8 Surname= Bloggs8 Category= HR
   Name= Jo7 Surname= Bloggs7 Category= Cleaning

class Program
{
    static void Main(string[] args)
    {
          List<Customer> listOne = new List<Customer>();
        List<Customer> listTwo = new List<Customer>();

        listOne.Add(new Customer { Category = "Account", Name = "Jo1", Surname = "Bloggs1" });
        listOne.Add(new Customer { Category = "Sales", Name = "Jo2", Surname = "Bloggs2" });
        listOne.Add(new Customer { Category = "Development", Name = "Jo5", Surname = "Bloggs5" });
        listOne.Add(new Customer { Category = "Management", Name = "Jo6", Surname = "Bloggs6" });



        listTwo.Add(new Customer { Category = "HR", Name = "Jo8", Surname = "Bloggs8" });
        listTwo.Add(new Customer { Category = "Sales", Name = "Jo2", Surname = "Bloggs2" });
        listTwo.Add(new Customer { Category = "Management", Name = "Jo6", Surname = "Bloggs6" });
        listTwo.Add(new Customer { Category = "Development", Name = "Jo5", Surname = "Bloggs5" });
        listTwo.Add(new Customer { Category = "Cleaning", Name = "Jo7", Surname = "Bloggs7" });


    List<Customer> resultList = listOne.Union(listTwo).ToList();//**I get duplicates why????**

        resultList.ForEach(customer => Console.WriteLine("Name= {0} Surname= {1} Category= {2}", customer.Name, customer.Surname, customer.Category));
        Console.Read();

        IEnumerable<Customer> resultList3 = listOne.Except(listTwo);//**Does not work**

        foreach (var customer in resultList3)
        {
            Console.WriteLine("Name= {0} Surname= {1} Category= {2}", customer.Name, customer.Surname, customer.Category);
        }

        **//Does not work**
        var resultList2 = (listOne
                       .Where(n => !(listTwo
                           .Select(o => o.Category))
                           .Contains(n.Category)))
                       .OrderBy(n => n.Category);

        foreach (var customer in resultList2)
        {
            Console.WriteLine("Name= {0} 
                             Surname= {1} 
                             Category= {2}", 

客户名称, 客户姓氏, 客户.类别); } Console.Read();

  }
}

public class Customer
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public string Category { get; set; }
}

【问题讨论】:

    标签: linq


    【解决方案1】:

    您不能使用ConcatDistinct LINQ 方法来做到这一点吗?

    List<Customer> listOne;
    List<Customer> listTwo;
    
    List<Customer> uniqueList = listOne.Concat(listTwo).Distinct().ToList(); 
    

    如有必要,您可以使用采用 IEqualityComparer 的 Distinct() 重载来创建自定义相等比较

    【讨论】:

    • 感谢您的回复。和 List resultList = listOne.Union(listTwo).ToList(); 一样吗?我仍然得到重复,可能是我的客户示例有问题
    • 我知道这篇文章已经过时了,但对于任何面临同样问题的人来说:您的客户可能是两个同名的不同对象。如果您想按名称(或任何其他属性)比较它们,您应该使用post 中描述的比较器
    【解决方案2】:

    问题的症结在于 Customer 对象没有 .Equals() 实现。如果您覆盖 .Equals (and .GetHashCode) 则 .Distinct 将使用它来消除重复项。但是,如果您不拥有 Customer 实现,则添加 .Equals 可能不是一种选择。

    另一种方法是将custom IEqualityComparer 传递给.Distinct()。这使您可以根据传入的比较器以不同的方式比较对象。

    另一个替代方法是 GroupBy 重要的字段并从组中获取任何项目(因为在这种情况下 GroupBy 充当 .Equals )。这需要编写最少的代码。

    例如

        var result = listOne.Concat(listTwo)
            .GroupBy(x=>x.Category+"|"+x.Name+"|"+x.Surname)
            .Select(x=>x.First());
    

    得到你想要的结果。

    【讨论】:

    • 嗨,这绝对有效。你能告诉我为什么要放置管道分隔符吗?我也会看看相等比较器
    • 作为一项规则,我使用唯一的分隔符来组合字段,以便应该不同的两个项目不会意外地组合到同一个键。考虑:如果不使用分隔符,{Name=abe, Surname=long} 和 {Name=abel, Surname=ong} 都会获得 GroupBy 键“abelong”。
    【解决方案3】:

    我有一个类似的问题,我有两个非常大的随机字符串列表。

    我做了一个递归函数,它返回一个带有唯一字符串的新列表。我比较了两个包含 100k 随机字符串的列表(它可能存在也可能不存在重复),每个列表都有 6 个字符 abcdefghijklmnopqrstuvwxyz1234567890,它在大约 230 毫秒内完成。我只测量了给定的函数。

    我希望这会给某人带来价值。

    Image of test run

    makeCodesUnique(List<string> existing, List<string> newL)
    {
        // Get all duplicate between two lists
        List<string> duplicatesBetween = newL.Intersect(existing).ToList();
    
        // Get all duplicates within list
        List<string> duplicatesWithin = newL.GroupBy(x => x)
        .Where(group => group.Count() > 1)
        .Select(group => group.Key).ToList();
    
        if (duplicatesBetween.Count == 0 && duplicatesWithin.Count == 0)
        {
            // Return list if there are no duplicates
            return newL; 
        }
        else
        {
            if (duplicatesBetween.Count != 0)
            {
                foreach (string duplicateCode in duplicatesBetween)
                {
                    newL.Remove(duplicateCode);
                }
    
                // Generate new codes to substitute the removed ones
                List<string> newCodes = generateSomeMore(duplicatesBetween.Count);
                newL.AddRange(newCodes);
                makeCodesUnique(existing, newL);
            }
            else if (duplicatesWithin.Count != 0)
            {
                foreach (string duplicateCode in duplicatesWithin)
                {
                    newL.Remove(duplicateCode);
                }
                List<string> newCodes = generateSomeMore(duplicatesWithin.Count);
                new.AddRange(newCodes);
                makeCodesUnique(existing, newL);
            }
        }
        return newL;
    }
    

    【讨论】:

      【解决方案4】:

      最好的选择是实现接口 IEqualityComparer 并在我在本文末尾写的 Union 或 Distinct 方法中使用它 http://blog.santiagoporras.com/combinar-listas-sin-duplicados-linq/

      • IEqualityComparer的实现

        公共类 SaintComparer : IEqualityComparer { public bool Equals(Saint item1, Saint item2) { 返回 item1.Name == item2.Name; }

        public int GetHashCode(Saint item)
        {
            int hCode = item.Name.Length;
            return hCode.GetHashCode();
        }
        

        }

      • 比较器的使用

        var unionList = list1.Union(list2, new SaintComparer());

      【讨论】:

        猜你喜欢
        • 2020-05-20
        • 2010-11-22
        • 2014-08-09
        • 1970-01-01
        • 1970-01-01
        • 2015-11-29
        • 2020-03-10
        • 2017-06-05
        • 1970-01-01
        相关资源
        最近更新 更多