Reputation: 48114
I have an instance of type List<string[]>
I would to convert this to a string with a each string[]
on a newline. I'm using the following LINQ query to flatten out the list however I'm not sure how I can add a new line between each string[]
without expanding my query into something far more ugly. Is there a way to do it without gutting my query and using String.Join
or IEnumerable.Aggregate
inside a foreach
loop?
results.SelectMany(x => x).Aggregate((c, n) => c + ", " + n)
Upvotes: 22
Views: 23995
Reputation: 3826
I like to use also extension methods for this flattening of a collection of string, and also be allowed to specify a line separator. Note the use of Trim here as we will have a trailing separator at the very end otherwise.
using System.Text;
namespace MultiLingual.Translator.Lib
{
public static class StringExtensions
{
/// <summary>
/// Merges a collection of lines into a flattened string separating each line by a specified line separator.
/// Newline is deafult
/// </summary>
/// <param name="inputLines"></param>
/// <param name="lineSeparator"></param>
/// <returns></returns>
public static string? FlattenString(this IEnumerable<string>? inputLines, string lineSeparator = "\n")
{
if (inputLines == null || !inputLines.Any())
{
return null;
}
var flattenedString = inputLines?.Aggregate(new StringBuilder(),
(sb, l) => sb.AppendLine(l + lineSeparator),
sb => sb.ToString().Trim());
return flattenedString;
}
}
}
Usage in a XUnit Test of mine :
[Theory]
[InlineData("Jeg er fra Norge og jeg liker brunost", "i'm from norway and i like brown cheese")]
public async Task TranslationReturnsExpected(string input, string expectedTranslation)
{
string? translation = await _translateUtil.Translate(LanguageCode.English, input, LanguageCode.Norwegian);
translation.Should().NotBeNull();
translation.Should().BeEquivalentTo(expectedTranslation);
}
Upvotes: 0
Reputation: 236268
String.Join(Environment.NewLine, results.Select(a => String.Join(", ", a)));
Complete sample:
var results = new List<string[]> {
new[]{"this", "should", "be", "on"},
new[]{"other", "line"}
};
var result = String.Join(Environment.NewLine,
results.Select(a => String.Join(", ", a)));
Result:
this, should, be, on
other, line
UPDATE Here is aggregation done right - it uses StringBuilder to build single string in memory
results.Aggregate(new StringBuilder(),
(sb, a) => sb.AppendLine(String.Join(",", a)),
sb => sb.ToString());
Upvotes: 60
Reputation: 22804
results.Select(sa => sa.Aggregate((a, b) => a + ", " + b))
.Aggregate((c, d) => c + Enviroment.NewLine + d);
Upvotes: 3