Model for my Application
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
public List<Person> Children { get; set; } = new List<Person>();
}
Nested List of Persons
List<Person> personList = new List<Person>();
Person parent = new Person() { ID = 1, Name = "A" };
parent.Children.Add(new Person() { ID = 2, Name = "B" });
parent.Children.Add(new Person() { ID = 3, Name = "C" });
personList.Add(parent);
parent = new Person() { ID = 2, Name = "D" };
parent.Children.Add(new Person() { ID = 4, Name = "E" });
parent.Children.Add(new Person()
{
ID = 5,
Name = "F",
Children = new List<Person>(){
new Person() { ID =6, Name = "G" },
new Person() { ID = 7, Name = "H" }}
});
personList.Add(parent);
personList.SelectMany(x => x.Children);
List of Ids in one list from all nested children using LINQ
CodePudding user response:
Please refer to this answer
Solution:
Create an extension method
public static class IEnumerableExtensions
{
public static IEnumerable<T> SelectManyRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (selector == null) throw new ArgumentNullException(paramName: nameof(selector));
return !source.Any() ? source :
source.Concat(
source
.SelectMany(i => selector(i).EmptyIfNull())
.SelectManyRecursive(selector)
);
}
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source)
{
return source ?? Enumerable.Empty<T>();
}
}
// ....
personList.Add(parent);
var flattenedLitOfPersons = personList.SelectManyRecursive(q => q.Children);
var ids = flattenedLitOfPersons.Select(q => q.ID);
CodePudding user response:
You could use this recursive extension method:
public static IEnumerable<T> Flatten<T>(this IEnumerable<T> seq, Func<T, IEnumerable<T>> getChildren)
{
foreach (var item in seq)
{
yield return item;
foreach (var subItem in getChildren(item).Flatten<T>(getChildren))
{
yield return subItem;
}
}
}
With your sample:
List<int> allPersonIdList = personList
.Flatten<Person>(p => p.Children)
.Select(p => p.ID)
.ToList();
If you want a unique list of ID's put a Distinct
before the ToList
.