My question is almost same as this one, but the List dimension is n.
How to concat all strings inside a List<List<List...<string>>
(n dimension list) using LINQ ?
NOTE: Interested for both cases, n is known or unknown
Since the linked question is tagged as c# so i add this answer with c# code.
If the number of nested lists are known You have to use SelectMany()
over and over to unwrap all the nested lists to sequence of chars. then make string out of that sequence.
List<List<List<string>>> nestedList = new List<List<List<string>>>();
var result = new string(nestedList.SelectMany(x => x).SelectMany(x => x).SelectMany(x => x).ToArray());
If the number of nested lists are not known you have to use reflection, since the type is not known. I didnt used reflection directly but actually dynamic type does. The performance would be terrible here of course ;) but it does what you want.
using Microsoft.CSharp.RuntimeBinder;
//...
private static string ConcatAll<T>(T nestedList) where T : IList
{
dynamic templist = nestedList;
try
{
while (true)
{
List<dynamic> inner = new List<dynamic>(templist).SelectMany<dynamic, dynamic>(x => x).ToList();
templist = inner;
}
}
catch (RuntimeBinderException)
{
List<object> l = templist;
return l.Aggregate("", (a, b) => a + b);
}
}
Here is the test
private static void Main(string[] args)
{
List<List<List<string>>> nestedList = new List<List<List<string>>>
{
new List<List<string>> {new List<string> {"Hello "}, new List<string> {"World "}},
new List<List<string>> {new List<string> {"Goodbye "}, new List<string> {"World ", "End "}}
};
Console.WriteLine(ConcatAll(nestedList));
}
Outputs:
Hello World Goodbye World End
Update:
After a bit fiddling i ended up this implementation. maybe better without try catch.
private static string ConcatAll<T>(T nestedList) where T : IList
{
dynamic templist = nestedList;
while (templist.Count > 0 && !(templist[0] is char?))
{
List<dynamic> inner = new List<dynamic>(templist).SelectMany<dynamic, dynamic>(x =>
{
var s = x as string;
if (s != null)
{
return s.Cast<dynamic>();
}
return x;
}).ToList();
templist = inner;
}
return new string(((List<object>) templist).Cast<char>().ToArray());
}
Another solution could be using a recursive method to flatten all your lists:
static IEnumerable<string> Flatten(IEnumerable enumerable)
{
foreach (object el in enumerable)
{
if (enumerable is IEnumerable<string>)
{
yield return (string) el;
}
else
{
IEnumerable candidate = el as IEnumerable;
if (candidate != null)
{
foreach (string nested in Flatten(candidate))
{
yield return nested;
}
}
}
}
}
With this method you can concat all the strings this way:
List<List<List<string>>> nestedList = new List<List<List<string>>>
{
new List<List<string>> {new List<string> {"Hello "}, new List<string> {"World "}},
new List<List<string>> {new List<string> {"Goodbye "}, new List<string> {"World ", "End "}}
};
Console.WriteLine(String.Join(" ",Flatten(nestedList)));
This idea was taken from this post.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With