Reputation: 63
I am trying to flatten a parent/child list, of the same <Person>
type. The difficulty here, is that I would
like to merge both the parents and children into a flat <Person>
list.
Closest I got was:
class Person
{
public string Name { get; set; }
public List<Person> Children { get; set; }
}
List<Person> parents = new List<Person>() {
new Person() {
Name = "parentA",
Children = new List<Person>() {
new Person() { Name = "childB" },
new Person() { Name = "childC" }
}
},
new Person() {
Name = "parentD",
Children = new List<Person>() {
new Person() { Name = "childE" },
new Person() { Name = "childF" }
}
}
};
var result = parents.SelectMany(parent => parent.Children
.Select(child => parent.Name + ", " + child.Name));
Which gives me the result:
parentA, childB
parentA, childC
parentD, childE
parentD, childF
What I'm looking for is to get a <Person>
list such as:
parentA
childB
childC
parentD
childE
childF
Keeping the order, or the performance is not important. But I would like, if possible, to stick to pure LINQ and LINQ methods.
Thanks,
Upvotes: 0
Views: 2742
Reputation: 63
Thanks to the comments on my initial post, I was able to get what I was looking for.
The solution only works on one level, which is what I needed. It could be made recursive to go deeper though:
var result = parents.SelectMany(person => person.Children
.Prepend(person))
.Select(p => p.Name);
Gave me the expected result:
parentA
childB
childC
parentD
childE
childF
Which then allowed me to use all the objects in the flattened lists, including the parent objects.
Upvotes: 3
Reputation: 34421
Try following class :
class Person
{
public static DataTable dt { get;set;}
public string Name { get; set; }
public List<Person> Children { get; set; }
public void GetTree(Person root)
{
DataTable dt = new DataTable();
dt.Columns.Add("Parent Name", typeof(string));
dt.Columns.Add("Child Name", typeof(string));
GetTreeRecursive(root, "");
}
public void GetTreeRecursive(Person person, string parentName)
{
foreach(Person child in person.Children)
{
dt.Rows.Add(parentName, child.Name);
if (child.Children != null)
{
GetTreeRecursive(child, child.Name);
}
}
}
}
Upvotes: 0
Reputation: 186668
I suggest Concat
in combination with SelectMany
if you want just one level deep:
var parents = ...
var result = parents
.SelectMany(person => new Person[] {person}.Concat(person.Children))
.Select(person => person.Name); // if we want just names
// Let's have a look
Console.WriteLine(string.Join(Environment.NewLine, result));
Upvotes: 1
Reputation: 33476
var persons = new List<Person>();
parents.ForEach(p => {
persons.Add(p);
persons.AddRange(p.Children);
}
);
foreach(var person in persons)
Console.WriteLine(person.Name);
}
I understand that this isnt a single line but this I suppose is what you are looking for.
Upvotes: 0