我有一个类文件,如下所述:
public class TestA
{
public string Name {get; set;}
public List<TestA> TestCollection {get;set;}
}
上面的您可以看到TestCollection
的类型是父类的列表。
现在我想从每个对象中检索名称。
我尝试使用SelectMany
,如下所示:但这对我不起作用。
testAList.SelectMany(t => t.Name)
我怎样才能做到这一点?
以下是小提琴代码:Fiddle Code
答案 0 :(得分:3)
假设testAList
是List<TestA>
,并且您希望每个Name
TestA
属性中的TestCollection
个对象的TestA
值testAList
内的对象:
testAList.SelectMany(x => x.TestCollection.Select(y => y.Name))
或者,如果您想要Name
中的testAList
个对象:
testAList.Select(x => x.Name)
最后,如果你想要所有的名字,你需要使用的不仅仅是LINQ,因为你的类的递归性质:
IEnumerable<string> GetNames(List<TestA> testAList)
{
return testAList.Select(x => x.Name)
.Concat(testAList.SelectMany(x => GetNames(x.TestCollection)));
}
var names = GetNames(testAList);
答案 1 :(得分:2)
您的集合是递归的,因此您需要递归查询才能获得结果:
IEnumerable<string> GetAllNames(TestA root) {
return GetNames(new[] {root}); // Forward to a method taking IEnumerable<T>
}
IEnumerable<string> GetAllNames(IEnumerable<TestA> tests) {
return tests
.Select(t => t.Name) // Names at this level
.Concat(tests.SelectMany(t => GetAllNames(t.TestCollection))); // Names of children
}
但是,C#提供了一种使用收益率回报的更好方法:
IEnumerable<string> GetAllNames(TestA node) {
yield return node.Name;
foreach (var childName in node.TestCollection.SelectMany(t => GetAllNames(t))) {
yield return childName;
}
}
答案 2 :(得分:0)
这是一个替代选项,它不使用linq但可以提供相同的结果
IEnumerable<string> GetAllNames(TestA root) {
return GetAllNames(new[] { root });
}
IEnumerable<string> GetAllNames(IEnumerable<TestA> tests) {
var queue = new Queue<TestA>(tests);
while (queue.Count > 0) {
var current = queue.Dequeue();
yield return current.Name;
if (current.TestCollection != null) {
foreach (var child in current.TestCollection) {
queue.Enqueue(child);
}
}
}
}
以上基于你的小提琴会产生
Parent_0
Parent_1
Parent_2
Parent_3
Parent_4
Child_0_0
Child_0_1
Child_1_0
Child_1_1
Child_2_0
Child_2_1
Child_3_0
Child_3_1
Child_4_0
Child_4_1
如果使用堆叠方法
IEnumerable<string> GetAllNamesStack(IEnumerable<TestA> tests) {
var stack = new Stack<TestA>(tests.Reverse());
while (stack.Count > 0) {
var current = stack.Pop();
yield return current.Name;
if (current.TestCollection != null) {
current.TestCollection.Reverse();
foreach (var child in current.TestCollection) {
stack.Push(child);
}
}
}
}
输出为
Parent_0
Child_0_0
Child_0_1
Parent_1
Child_1_0
Child_1_1
Parent_2
Child_2_0
Child_2_1
Parent_3
Child_3_0
Child_3_1
Parent_4
Child_4_0
Child_4_1