【问题标题】:Remove elements in a list considering duplicated subelements考虑到重复的子元素,删除列表中的元素
【发布时间】:2018-05-29 02:50:18
【问题描述】:

考虑到一个或多个重复的子元素,我需要删除单个列表中的元素

public class Person
{
    public int id { get; set; }
    public string name { get; set; }
    public List<IdentificationDocument> documents { get; set; }

    public Person()
    {
        documents = new List<IdentificationDocument>();
    }
}

public class IdentificationDocument
{
    public string number { get; set; }
}

代码:

        var person1 = new Person() {id = 1, name = "Bob" };
        var person2 = new Person() {id = 2, name = "Ted" };
        var person3 = new Person() {id = 3, name = "Will_1" };
        var person4 = new Person() {id = 4, name = "Will_2" };

        person1.documents.Add(new IdentificationDocument() { number = "123" });
        person2.documents.Add(new IdentificationDocument() { number = "456" });
        person3.documents.Add(new IdentificationDocument() { number = "789" });
        person4.documents.Add(new IdentificationDocument() { number = "789" }); //duplicate

        var personList1 = new List<Person>();

        personList1.Add(person1);
        personList1.Add(person2);
        personList1.Add(person3);
        personList1.Add(person4);

        //more data for performance test
        for (int i = 0; i < 20000; i++)
        {
            var personx = new Person() { id = i, name = Guid.NewGuid().ToString() };
            personx.documents.Add(new IdentificationDocument() { number = Guid.NewGuid().ToString() });
            personx.documents.Add(new IdentificationDocument() { number = Guid.NewGuid().ToString() });
            personList1.Add(personx);
        }

        var result = //Here comes the linq query

        result.ForEach(r => Console.WriteLine(r.id + " " +r.name));

预期结果:

1 鲍勃 2泰德 3 意志_1

例子

https://dotnetfiddle.net/LbPLcP

谢谢!

【问题讨论】:

  • 删除哪个重要吗?您说您希望删除第 4 个人,但标准是什么?它只是在列表中的放置顺序,较早的优先吗?如果您添加了第五个人并且他们有两个与列表中的其他两个匹配的身份证件会发生什么(假设他们有 123 和 456 作为他们的证件)。您要保留有 2 个文档的人并删除另外两个人吗?

标签: c# performance list linq duplicates


【解决方案1】:

按照亚当的解决方案,诀窍是迭代人员并按相关文档编号对他们进行分组。

// persons with already assigned documents
// Will_2
var duplicate = from person in personList1
                from document in person.documents
                group person by document.number into groupings
                let counter = groupings.Count()
                where counter > 1
                from person in groupings
                    .OrderBy(p => p.id)
                    .Skip(1)
                select person;

// persons without already assigned documents
// Bob
// Ted
// Will_1
var distinct = from person in personList1
               from document in person.documents
               group person by document.number into groupings
               from person in groupings
                   .OrderBy(p => p.id)
                   .Take(1)
               select person;

orderby 是为已分配文件的人员制定的规则,但您的里程可能会有所不同

【讨论】:

    【解决方案2】:

    嗯,是的,您可以使用自定义比较器。但这将比您的特定示例所需的代码多得多。如果您只需要您的具体示例,这将正常工作:

    var personDocumentPairs = personList1
        .SelectMany(e => e.documents.Select(t => new {person = e, document = t}))
        .GroupBy(e => e.document.number).Select(e => e.First());
    var result = personDocumentPairs.Select(e => e.person).Distinct();
    

    【讨论】:

      【解决方案3】:

      您可以使用 LINQ 中的 Enumerable.Distinct&lt;TSource&gt; 方法。您需要创建一个自定义比较器以使用子元素进行比较。

      How do I use a custom comparer with the Linq Distinct method?

      【讨论】:

        猜你喜欢
        • 2021-06-29
        • 1970-01-01
        • 1970-01-01
        • 2018-05-02
        • 2014-07-06
        • 1970-01-01
        • 2020-01-19
        • 2020-08-02
        • 2020-11-02
        相关资源
        最近更新 更多