Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List<string[]> determine max length by Linq

Tags:

c#

list

linq

I have the following structure

List<string[]> sList = new List<string[]>() {
    new[] { "x", "xxx", "xxxx" },  //1,3,4
    new[] { "x", "xx", "xx" },     //1,2,2
    new[] { "xxxxxx", "xx", "xx" } //6,2,2
};

and I need to determine the maximum string.length of the items by column

In this example the expected result should be:

List<int> Result = new List<int>() { 6, 3, 4 };

Is there a easy Linq-approach?

my effort (working but not using Linq):

List<int> Result = new List<int>();
foreach (string[] line in Table)
{
    for (int i = 0; i < line.Length; i++)
    {
        if (Result.Count > i)
        {
            if (Result[i] < line[i].Length)
            {
                Result[i] = line[i].Length;
            }
        }
        else
        {
            Result.Insert(i, line[i].Length);
        }
    }
}

the number of rows/columns is dynamic but each row has the same number of columns.

like image 600
Byyo Avatar asked Sep 22 '15 12:09

Byyo


2 Answers

One approach:

int maxColumns = sList.Max(arr => arr.Length);
List<int> Result = Enumerable.Range(0, maxColumns)
    .Select(i => sList.Max(arr => (arr.ElementAtOrDefault(i) ?? "").Length))
    .ToList();

You want the max-length per column. The columns are the array indices. So you need a way to look at the arrays per index. Therefore i've used Enumerable.Range(0, maxColumns). Then i'm using ElementAtOrDefault to handle the case that the array doesn't contain so many "columns"(not needed as i'm explaining below). That returns null for reference types like string. I replace them with the null-coalescing operator with "" which yields 0 as length.

Since you've mentioned that "each row has the same number of columns" you can make it a little bit more readable:

List<int> Result = Enumerable.Range(0, sList.First().Length)
    .Select(i => sList.Max(arr => arr[i].Length))
    .ToList();
like image 26
Tim Schmelter Avatar answered Sep 18 '22 22:09

Tim Schmelter


This is the best that I could come up with:

List<int> Result = sList.First().Select((x, i) => sList.Max(y => y[i].Length)).ToList();

Bonus points for one line?

Explanation: Since you said that they all have the same number of elements, take the first row and loop through that. Use the index to get that element from each of the other rows getting the length and then the maximum of that.

like image 138
TomDoesCode Avatar answered Sep 19 '22 22:09

TomDoesCode