我有一个Class1类型的对象。 Class1具有以下属性:member(int),parent(Class1),lstMembers(属于Class1)。
例如:
对象A没有父级(父级== null)。在对象A的列表中,我们当然有两个Class1类型的对象A1和A2。在对象A1的列表中,我们有一个对象A11。在对象A2的列表中,我们有一个对象A21。
A -> A1, A2
A1 -> A11
A2 -> A21
因此,树中包含三个级别。级别数是已知的。我想使用LINQ和递归获取树中每个对象的属性Member的值。我似乎找不到解决方案。请注意,由于某些特殊原因,我无法删除列表中的对象。我确实找到了一种解决方案,其中包括从嵌套列表中删除对象(递归解决方案)。
从列表中删除对象的示例代码:
static void GetMembers(Class1 child, Class1 parent, ref List<int> lstMember)
{
// last level
if (child.lstC.Count == 0)
{
lstMember.Add(child.member);
Console.WriteLine(child.member + " added " + child.name);
// remove all from last level
if (parent != null)
{
parent.lstC.Remove(child);
if (parent.lstC.Count != 0)
GetMembers(parent.lstC.First(), parent, ref lstMember);
}
}
// group level
else
{
GetMembers(child.lstC.First(), child, ref lstMember);
if (parent != null && parent.lstC.Count != 0)
{
GetMembers(parent.lstC.First(), parent, ref lstMember);
}
else
{
GetMembers(child, null, ref lstMember);
}
}
}
我想获取商品而不用LINQ删除商品
答案 0 :(得分:0)
我为您制作了两种扩展方法。
首先搜索要测试的是树中是否有项目。
注意:之所以不能从列表中删除,是因为在枚举时不能对其进行更改。这是集合的安全。答案是复制列表或集合。我已经在提供的删除代码示例中使用ToList()
完成了此操作。请注意,由于没有更改,因此在搜索版本中无需这样做。
您提供了搜索方式。 您提供了访问嵌套类型的方法。
下面是在树中搜索项目的示例:
var isInTree = dataList.FoundInTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData);
下面是从树中删除项目的示例:
var removedFromTree = dataList.RemoveFirstFromTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData);
我包含了这些方法的重载/变化形式,以允许搜索/删除多个相同的项目:
var isInTree = dataList.FoundInTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData,
out int foundCount);
var removedFromTree = dataList.RemoveAllFromTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData,
out int removedCount);
我还提供了一个示例应用程序,该应用程序模拟了显示如何使用它的数据,但首先是扩展方法:
扩展方法(这是您在代码中的答案)
public static class Extensions
{
public static bool FoundInTree<T>(this IEnumerable<T> items, Func<T, bool> searchItem, Func<T, IEnumerable<T>> nestedItems)
{
foreach (var item in items)
{
if (searchItem.Invoke(item)) return true;
if (nestedItems.Invoke(item).FoundInTree(searchItem, nestedItems)) return true;
}
return false;
}
public static bool RemoveFirstFromTree<T>(this ICollection<T> items, Func<T, bool> searchItem, Func<T, ICollection<T>> nestedItems)
{
foreach (var item in items.ToList())
{
if (searchItem.Invoke(item))
{
items.Remove(item);
return true;
}
if (nestedItems.Invoke(item).RemoveFirstFromTree(searchItem, nestedItems))
{
return true;
}
}
return false;
}
public static bool FoundInTree<T>(this IEnumerable<T> items, Func<T, bool> searchItem, Func<T, IEnumerable<T>> nestedItems, out int count)
{
count = 0;
foreach (var item in items)
{
if (searchItem.Invoke(item)) count++;
if (nestedItems.Invoke(item).FoundInTree(searchItem, nestedItems, out int nestedCount)) count += nestedCount;
}
return count > 0;
}
public static bool RemoveAllFromTree<T>(this ICollection<T> items, Func<T, bool> searchItem, Func<T, ICollection<T>> nestedItems, out int count)
{
var isAnyRemoved = false;
count = 0;
foreach (var item in items.ToList())
{
if (searchItem.Invoke(item))
{
items.Remove(item);
isAnyRemoved = true;
count++;
}
if (nestedItems.Invoke(item).RemoveAllFromTree(searchItem, nestedItems, out int nestedCount))
{
isAnyRemoved = true;
count += nestedCount;
}
}
return isAnyRemoved;
}
}
现在是完整的控制台应用程序(包括扩展方法)。您可以按原样复制并粘贴它,然后根据需要使用它。
控制台应用程序
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
namespace Question_Answer_Console_App
{
class Program
{
static void Main(string[] args)
{
var dataList = GetMockData();
var isInTree = dataList.FoundInTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData,
out int foundCount);
if (isInTree)
{
Console.WriteLine($"Found {foundCount} items in the tree.");
}
else
{
Console.WriteLine("None found in the tree.");
}
var removedFromTree = dataList.RemoveAllFromTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData,
out int removedCount);
if (removedFromTree)
{
Console.WriteLine($"Removed {removedCount} items from the tree.");
}
else
{
Console.WriteLine($"No items removed from the tree.");
}
isInTree = dataList.FoundInTree(searchItem: item => item.Id == 6,
nestedItems: (item) => item.NestedData);
if (isInTree)
{
Console.WriteLine($"Found {foundCount} items in the tree.");
}
else
{
Console.WriteLine("None found in the tree.");
}
Console.ReadKey();
}
private static List<Data<int>> GetMockData()
{
var dataList = new List<Data<int>>();
for (var i = 0; i < 7; i++)
{
dataList.Add(getData(i));
}
return dataList;
Data<int> getData(int count)
{
var data = new Data<int>
{
Id = count
};
for (var j = count; j > 0; j--)
{
var innerData = new Data<int>
{
Id = j
};
innerData.NestedData.Add(getData(--j));
data.NestedData.Add(innerData);
}
return data;
}
}
}
public class Data<T>
{
public T Id { get; set; }
public List<Data<T>> NestedData { get; set; } = new List<Data<T>>();
}
public static class Extensions
{
public static bool FoundInTree<T>(this IEnumerable<T> items, Func<T, bool> searchItem, Func<T, IEnumerable<T>> nestedItems)
{
foreach (var item in items)
{
if (searchItem.Invoke(item)) return true;
if (nestedItems.Invoke(item).FoundInTree(searchItem, nestedItems)) return true;
}
return false;
}
public static bool RemoveFirstFromTree<T>(this ICollection<T> items, Func<T, bool> searchItem, Func<T, ICollection<T>> nestedItems)
{
foreach (var item in items.ToList())
{
if (searchItem.Invoke(item))
{
items.Remove(item);
return true;
}
if (nestedItems.Invoke(item).RemoveFirstFromTree(searchItem, nestedItems))
{
return true;
}
}
return false;
}
public static bool FoundInTree<T>(this IEnumerable<T> items, Func<T, bool> searchItem, Func<T, IEnumerable<T>> nestedItems, out int count)
{
count = 0;
foreach (var item in items)
{
if (searchItem.Invoke(item)) count++;
if (nestedItems.Invoke(item).FoundInTree(searchItem, nestedItems, out int nestedCount)) count += nestedCount;
}
return count > 0;
}
public static bool RemoveAllFromTree<T>(this ICollection<T> items, Func<T, bool> searchItem, Func<T, ICollection<T>> nestedItems, out int count)
{
var isAnyRemoved = false;
count = 0;
foreach (var item in items.ToList())
{
if (searchItem.Invoke(item))
{
items.Remove(item);
isAnyRemoved = true;
count++;
}
if (nestedItems.Invoke(item).RemoveAllFromTree(searchItem, nestedItems, out int nestedCount))
{
isAnyRemoved = true;
count += nestedCount;
}
}
return isAnyRemoved;
}
}
}
//OUTPUTS //Found 2 items in the tree. //Removed 2 items from the tree. //None found in the tree.
答案 1 :(得分:0)
您在这里:
class Class1
{
public Class1(string Name)
{
lstC = new List<Class1>();
this.name = Name;
}
public List<Class1> lstC { get; set; }
public string name { get; }
public int member { get; set; }
}
class Program
{
static void Main(string[] args)
{
Class1 par = new Class1("A") { member = 4 };
Class1 c1 = new Class1("A1") { member = 54};
Class1 c2 = new Class1("A2") { member = 5 };
par.lstC.Add(c1);
par.lstC.Add(c2);
Class1 c11 = new Class1("A11") { member = 39 };
c1.lstC.Add(c11);
Class1 c21 = new Class1("A21") { member = 67 };
c2.lstC.Add(c21);
List<int> result = new List<int>();
GetMembers(par, ref result);
}
static void GetMembers(Class1 parent, ref List<int> lstMember)
{
lstMember.Add(parent.member);
foreach (var child in parent.lstC)
{
GetMembers(child, ref lstMember);
}
}
}
答案 2 :(得分:0)
这就是我最后的结果,希望能在正确的抽象水平上
void Main()
{
var dataStructure = Init_DataStructure();
List<int> members = GetMembers(dataStructure).ToList();
}
IEnumerable<int> GetMembers(Class1 input)
{
yield return input.Member;
foreach (var subMember in input.MemberList.SelectMany(c => GetMembers(c)))
yield return subMember;
}
Class1 Init_DataStructure()
{
Class1
a1 = new Class1
{
Id = "A1",
Member = 1,
MemberList = new Collection<Class1>()
},
a11 = new Class1
{
Id = "A11",
Member = 2,
Parent = a1
};
a1.MemberList.Add(a11);
Class1
a2 = new Class1
{
Id = "A2",
Member = 3,
MemberList = new Collection<Class1>()
},
a21 = new Class1
{
Id = "A21",
Member = 4,
Parent = a2
};
a2.MemberList.Add(a21);
return new Class1
{
Id = "A",
Member = 0,
MemberList = new Collection<Class1> { a1, a2 }
};
}
class Class1
{
public Class1() => MemberList = new Collection<Class1>();
public Class1 Parent { get; set; }
public string Id { get; set; }
public int Member { get; set; }
public ICollection<Class1> MemberList { get; set; }
}