C# 从复合列表C中筛选出对象#

C# 从复合列表C中筛选出对象#,c#,linq,list,C#,Linq,List,我的综合清单如下: List<RestApiD3Output> result = new List<RestApiD3Output>(); 期望的输出是- { "name": "Ford", "children": [ { "name": "Figo", "children": [ { "name": "Test", "size": 3938 }

我的综合清单如下:

List<RestApiD3Output> result = new List<RestApiD3Output>();
期望的输出是-

{
    "name": "Ford",
    "children": [
        {
            "name": "Figo",
            "children": [
                { "name": "Test", "size": 3938 }
            ]
        },
        {
            "name": "Test",
            "children": [
                { "name": "Test1", "size": 3938 },
                { "name": "Test2", "size": 3938 },
                { "name": "Test3", "size": 3938 }
            ]
        }
    ]
}
编辑-

对一些问题的澄清


因为父节点的名称是Test,所以我希望拥有整个节点及其所有子节点。因此出现了Test1和Test2

如果父节点的名称不是test,但是有一个子节点的名称是test,那么我希望节点只有子元素的名称是test

编辑2

情景-

  • 如果父项名为“Test”,则保留它及其所有子项
  • 如果父项未命名为“Test”,但有任何子项命名为“Test”,则只需将该子项的名称保留为“Test”,并删除其余子项
  • 否则,删除该项

  • 如果在所有级别使用同一个类,则可以使用递归方法。上课

    public class Item
    {
        public string name { get; set; }
        public int size { get; set; }
        public IList<Item> children { get; set; }
    }
    

    更新

    在您澄清之后,这里是另一个满足以下规则的解决方案:

  • 如果项目名为“测试”,则保留该项目及其所有子项
  • 如果一个项目有任何名为“Test”的子项,请保留它
  • 否则,删除该项
  • public void PruneTree(IList项)
    {
    对于(int i=items.Count-1;i>=0;i--){
    项目=项目[i];
    如果(item.name!=“测试”){
    PruneTree(项目.子项);
    如果(item.children.Count==0){
    项目.删除(i);
    }
    }
    }
    }
    
    调用PruneTree前后的测试输出:

    这是我的整个测试课程:

    public static class FilteringOutObjectFromCompositeList
    {
        public class Item
        {
            public Item()
            {
                children = new List<Item>();
            }
    
            public string name { get; set; }
            public int size { get; set; }
            public IList<Item> children { get; set; }
        }
    
        private static void PruneTree(IList<Item> items)
        {
            for (int i = items.Count - 1; i >= 0; i--) {
                Item item = items[i];
                if (item.name != "Test") {
                    PruneTree(item.children);
                    if (item.children.Count == 0) {
                        items.RemoveAt(i);
                    }
                }
            }
        }
    
        public static void Test()
        {
            var root = new Item {
                name = "Ford",
                children = new List<Item> {
                     new Item {
                        name = "Figo",
                        children = new List<Item> {
                            new Item { name= "Test", size= 3938 },
                            new Item { name= "Test1", size= 3938 },
                            new Item {
                                name= "Test2",
                                children = new List<Item> {
                                    new Item { name= "Test-1-1", size= 3938 },
                                    new Item { name= "Test-1-2", size= 3938 }
                                }
                            }
                        }
                    },
                    new Item {
                        name= "Test",
                        children=new List<Item> {
                            new Item { name= "Test1", size= 3938 },
                            new Item { name= "Test2", size= 3938 },
                            new Item { name= "Test3", size= 3938 }
                        }
                    }
                }
            };
            PrintTree(root, 0);
            PruneTree(root.children);
            Console.WriteLine("----------------------");
            PrintTree(root, 0);
            Console.ReadKey();
        }
    
        private static void PrintTree(Item item, int level)
        {
            PrintIndent(level);
            Console.Write("name = " + item.name);
            if (item.size != 0) {
                PrintIndent(level);
                Console.Write("size = " + item.size);
            }
            Console.WriteLine();
            foreach (var child in item.children) {
                PrintTree(child, level + 1);
            }
        }
        private static void PrintIndent(int level)
        {
            Console.Write(new String(' ', 4 * level));
        }
    }
    
    公共静态类筛选器GoutObjectFromCompositeList
    {
    公共类项目
    {
    公共项目()
    {
    children=新列表();
    }
    公共字符串名称{get;set;}
    公共整数大小{get;set;}
    公共IList子项{get;set;}
    }
    私有静态void PruneTree(IList项)
    {
    对于(int i=items.Count-1;i>=0;i--){
    项目=项目[i];
    如果(item.name!=“测试”){
    PruneTree(项目.子项);
    如果(item.children.Count==0){
    项目.删除(i);
    }
    }
    }
    }
    公共静态无效测试()
    {
    var root=新项目{
    name=“福特”,
    儿童=新列表{
    新项目{
    name=“Figo”,
    儿童=新列表{
    新项{name=“Test”,size=3938},
    新项目{name=“Test1”,大小=3938},
    新项目{
    name=“Test2”,
    儿童=新列表{
    新项目{name=“Test-1-1”,大小=3938},
    新项目{name=“Test-1-2”,大小=3938}
    }
    }
    }
    },
    新项目{
    name=“Test”,
    儿童=新列表{
    新项目{name=“Test1”,大小=3938},
    新项目{name=“Test2”,大小=3938},
    新项目{name=“Test3”,大小=3938}
    }
    }
    }
    };
    printree(根,0);
    PruneTree(root.children);
    控制台写入线(“-------------------------”);
    printree(根,0);
    Console.ReadKey();
    }
    私有静态void打印树(项目,int级别)
    {
    打印缩进(水平);
    Console.Write(“name=“+item.name”);
    如果(item.size!=0){
    打印缩进(水平);
    Console.Write(“size=“+item.size”);
    }
    Console.WriteLine();
    foreach(item.children中的变量child){
    打印树(子级,级别+1);
    }
    }
    专用静态void打印缩进(整数级)
    {
    写入(新字符串(“”,4*级));
    }
    }
    
    好了

    var filteredResult = result.Where(x => x.name != "test" || x.children.Count(c => c.name != "test") > 0 );
    

    选择父名称不为“test”或任何子名称不为“test”的行。

    示例对我来说没有意义,您可以删除
    Test1
    ,但不删除
    Test1
    。是否确实要与
    ==
    而不是与
    包含的
    进行比较?为什么保留
    的“Test1”
    ,而不是
    的“Test-1-1”
    ?您的模型在不同级别上略有不同。这真的有必要吗?只有一个类和一个完全递归的结构不是更容易吗?因为父节点的名称是Test,所以我希望有整个节点及其所有子节点。因此出现了Test1和Test2。如果父节点的名称不是test,但是有一个子节点的名称是test,那么我希望节点只有子元素的名称是test。嗨,Oliver,你的评论很有用,但是我仍然得到了一些其他节点值,而不是所需的集。嗨,Oliver,尝试了你的解决方案,1和3工作得很好。至于你的第2点-如果一个项目有任何名为“Test”的子项,只需保留该项目名为“Test”的子项,并删除其余的子项Yes。规则是递归应用的。由于子项是“项”,规则3将自动应用于这些子项。更新方案-如果父项名为“测试”,则保留它及其所有子项。如果父项未命名为“Test”,但有任何子项命名为“Test”,只需保留该项的名为“Test”的子项,并删除其余子项,否则将删除该项。根据您给出的解决方案,我仍将获取名为“Test”的子节点
    private bool KeepIt(Item item)
    {
        return item.name.StartsWith("Test");
    }
    
    // This first solution removes all the nodes not having a name starting with "Test" and not
    // having any children fulfilling the same condition. But, apparently this was not what the
    /// OP wanted. Please, see my update.
    public void PruneTree(IList<Item> items)
    {
        for (int i = items.Count-1; i >= 0; i--) {
            PruneTree(items[i].children);
            if (items[i].children.Count == 0 && !KeepIt(items[i])) {
                items.RemoveAt(i);
            }
        }
    }
    
    PruneTree(result);
    
    public void PruneTree(IList<Item> items)
    {
        for (int i = items.Count - 1; i >= 0; i--) {
            Item item = items[i];
            if (item.name != "Test") {
                PruneTree(item.children);
                if (item.children.Count == 0) {
                    items.RemoveAt(i);
                }
            }
        }
    }
    
    public static class FilteringOutObjectFromCompositeList
    {
        public class Item
        {
            public Item()
            {
                children = new List<Item>();
            }
    
            public string name { get; set; }
            public int size { get; set; }
            public IList<Item> children { get; set; }
        }
    
        private static void PruneTree(IList<Item> items)
        {
            for (int i = items.Count - 1; i >= 0; i--) {
                Item item = items[i];
                if (item.name != "Test") {
                    PruneTree(item.children);
                    if (item.children.Count == 0) {
                        items.RemoveAt(i);
                    }
                }
            }
        }
    
        public static void Test()
        {
            var root = new Item {
                name = "Ford",
                children = new List<Item> {
                     new Item {
                        name = "Figo",
                        children = new List<Item> {
                            new Item { name= "Test", size= 3938 },
                            new Item { name= "Test1", size= 3938 },
                            new Item {
                                name= "Test2",
                                children = new List<Item> {
                                    new Item { name= "Test-1-1", size= 3938 },
                                    new Item { name= "Test-1-2", size= 3938 }
                                }
                            }
                        }
                    },
                    new Item {
                        name= "Test",
                        children=new List<Item> {
                            new Item { name= "Test1", size= 3938 },
                            new Item { name= "Test2", size= 3938 },
                            new Item { name= "Test3", size= 3938 }
                        }
                    }
                }
            };
            PrintTree(root, 0);
            PruneTree(root.children);
            Console.WriteLine("----------------------");
            PrintTree(root, 0);
            Console.ReadKey();
        }
    
        private static void PrintTree(Item item, int level)
        {
            PrintIndent(level);
            Console.Write("name = " + item.name);
            if (item.size != 0) {
                PrintIndent(level);
                Console.Write("size = " + item.size);
            }
            Console.WriteLine();
            foreach (var child in item.children) {
                PrintTree(child, level + 1);
            }
        }
        private static void PrintIndent(int level)
        {
            Console.Write(new String(' ', 4 * level));
        }
    }
    
    var filteredResult = result.Where(x => x.name != "test" || x.children.Count(c => c.name != "test") > 0 );