简体   繁体   English

如何在 C# 中迭代​​时从嵌套列表中删除所有项目

[英]How to remove all items from nested list while iterating in C#

I have a nested list that contains我有一个嵌套列表,其中包含

public class Person
{
    public Person(string name)
    {
        this.Name = name;
    }

    public string Name { get; set; }

    public List<Person> Childs { get; set; }
}

The list can be used like:该列表可以像这样使用:

    var Persons = new List<Person>();
    Persons.Add(new Person("Eric"));
    Persons[0].Childs = new List<Person>();
    Persons[0].Childs.Add(new Person("Tom"));
    Persons[0].Childs.Add(new Person("John"));
    Persons[0].Childs[0].Childs = new List<Person>();
    Persons[0].Childs[0].Childs.Add(new Person("Bill"));
    Persons.Add(new Person("John");

How can I iterate over the list Persons and remove all items with the name "John"?如何遍历列表Persons并删除所有名为“John”的项目? If the name is John the node with the name John and all underlaying subitems should be removed.如果名称为 John,则应删除名为 John 的节点和所有底层子项。

You're better off not removing the elements from the existing structure but instead to return a new structure without the "John"'s.您最好不要从现有结构中删除元素,而是返回一个没有“John”的新结构。

Here's how:就是这样:

List<Person> Except(List<Person> people, string name) =>
    people
        .Where(p => p.Name != name)
        .Select(p => new Person(p.Name)
        {
            Childs = Except(p.Childs ?? new List<Person>(), name) // Case typo in method name
        })
        .ToList();

If you start with your original data:如果您从原始数据开始:

var Persons = new List<Person>()
{
    new Person("Eric")
    {
        Childs = new List<Person>()
        {
            new Person("Tom"),
            new Person("John")
            {
                Childs = new List<Person>()
                {
                    new Person("Bill")
                }
            }
        }
    },
    new Person("John")
};

You can now run this:你现在可以运行这个:

List<Person> PersonsNotJohn = Except(Persons, "John");

That gives:这给出了:

人不是约翰

Here is a recursive method that removes all persons with the specified name.这是一个递归方法,它删除所有具有指定名称的人。 You can call it like RemoveAllWithName(Persons, "John");您可以将其称为RemoveAllWithName(Persons, "John"); . .

private void RemoveAllWithName(List<Person> people, string name)
{
    for(int i = people.Count - 1; i >= 0; --i) {
        Person person = people[i];
        if(person.Name == name) {
            people.RemoveAt(i);
        } else if(person.Childs != null) {
            RemoveAllWithName(person.Childs, name);
        }
    }
}

Here you go.干得好。

Add Namespace添加命名空间

using System.Linq;

Use the below one liner使用下面的一个衬垫

Persons.RemoveAll(x => x.Name == "John");
static void Main(string[] args)
    {
        var Persons = new List<Person>();
        Persons.Add(new Person("Eric"));
        Persons[0].Childs = new List<Person>();
        Persons[0].Childs.Add(new Person("Tom"));
        Persons[0].Childs.Add(new Person("John"));
        Persons[0].Childs[0].Childs = new List<Person>();
        Persons[0].Childs[0].Childs.Add(new Person("Bill"));
        Persons.Add(new Person("John"));
        RemoveAllWithName("John", Persons);
        Persons.ForEach(x=>Print(x));
    }
    private static void RemoveAllWithName(string name, List<Person> persons)
    {
        if (persons != null && persons.Any())
        {
            persons.RemoveAll(x => x.Name == name);
        }
        if (persons != null && persons.Any())
        {
            persons.ForEach(x => RemoveAllWithName(name, x.Childs));
        }
    }
    private static void Print(Person person)
    {
        if (person != null)
        {
            Console.WriteLine(person.Name);
            person.Childs?.ForEach(Print);
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM