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 情景-
如果在所有级别使用同一个类,则可以使用递归方法。上课
public class Item
{
public string name { get; set; }
public int size { get; set; }
public IList<Item> children { get; set; }
}
更新 在您澄清之后,这里是另一个满足以下规则的解决方案:
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 );