Reputation: 2050
I have a simple class with a tree structure like this
public class Item
{
public int ID { get; set; }
public List<Item> Items { get; set; }
}
with some sample data like this
// [1]
// / | \
// [2][3][4]
// / \
// [5][6]
Item alt = new Item()
{
ID = 1,
Items = new List<Item>() {
new Item() { ID = 2 }, new Item() {
ID = 3, Items = new List<Item>() {
new Item() { ID = 5 },
new Item() { ID = 6 }
}
},
new Item() { ID = 4 }
}
};
now I want to flatten the result into a array with all child nodes (except root node) to the end expected result:
[2]
[3][5]
[3][6]
[4]
I've tried something like
public static IEnumerable<IEnumerable<Item>> Flatten(Item alt)
{
if (alt.Items != null)
foreach (var altsub in alt.Items)
yield return Flatten(altsub);
}
but that doesn't seem to work as expected. Any suggestions?
Upvotes: 0
Views: 250
Reputation: 117064
Here you go:
public static IEnumerable<IEnumerable<Item>> Flatten(Item alt)
{
IEnumerable<IEnumerable<Item>> Flatten(Item[] a)
{
if (a.Last().Items == null)
{
yield return a;
}
else
{
foreach (var c in a.Last().Items)
foreach (var x in Flatten(a.Concat(new [] { c }).ToArray()))
yield return x;
}
}
if (alt.Items != null)
{
foreach (var c in alt.Items)
foreach (var x in Flatten(new [] { c }))
yield return x;
}
}
Given your sample input you can run it like this:
Console.WriteLine(
String.Join(
Environment.NewLine,
Flatten(alt).Select(xs =>
String.Concat(xs.Select(x => $"[{x.ID}]")))));
That gives me:
[2]
[3][5]
[3][6]
[4]
Upvotes: 4