3

Consider 2D array like this one:

enter image description here

With the following code the empty rows are skipped:

public static string[,] SkipBlankRows(this string[,] array2D)
{
    var columns = array2D.GetLength(1);
    var rows = array2D.GetLength(0);
    var temp = new List<string[]>();

    for (var r = 0; r < rows; r++)
    {
        var row = new string[columns];
        for (var c = 0; c < columns; c++)
        {
            row[c] = array2D[r, c];
        }
        if (row.All(itm => string.IsNullOrWhiteSpace(itm)))
            continue;
        temp.Add(row);
    }

    string[,] result = new string[temp.Count(), columns];
    rows = temp.Count();

    for (int r = 0; r < rows; r++)
    {
        var row = temp[r];
        for (var c = 0; c < row.Length; c++)
        {
            result[r,c]=row[c];
        }
    }
    return result;
}

Usage:

void Main()
{
    var x = new string[,] { { "", "", "" }, { "", "X", "" }, { "X", "X", "X" }, { "", "", "" }, {"X","","X"}, {"X","X","X"}};
    var y = x.SkipBlankRows();
}

Result:

The result should be 2D-array of string where the blank rows will not be there.

enter image description here

The code looks awkward to me, is it possible to do it better e.g. to involve linq?

1
  • Might be worth explaining what you would like your output to look like Commented Feb 20, 2020 at 15:13

3 Answers 3

2

You could use LINQ to get the string[,] to an IEnumerable<IEnumerable<string>> with the empty rows removed, then put the IEnumerable<IEnumerable<string>> back into a string[,]. I'm not aware of any way with LINQ to project an IEnumerable<IEnumerable<string>> into a string[,], so I just used nested foreach loops.

public static string[,] SkipBlankRows(this string[,] array2D)
{
    int columnCount = array2D.GetLength(1);

    var withoutEmptyLines = array2D
        .Cast<string>()  // Flatten the 2D array to an IEnumerable<string>
        .Select((str, idx) => new { str, idx }) // Select the string with its index
        .GroupBy(obj => obj.idx / columnCount) // Group the items into groups of "columnCount" items
        .Select(grp => grp.Select(obj => obj.str)) // Select the groups into an IEnumerable<IEnumerable<string>>
        .Where(strs => !strs.All(str => string.IsNullOrWhiteSpace(str))); // Filter empty rows;

    // Put the IEnumerable<IEnumerable<string>> into a string[,].
    var result = new string[withoutEmptyLines.Count(), columnCount];
    int rowIdx = 0;
    foreach (var row in withoutEmptyLines)
    {
        int colIdx = 0;
        foreach (var col in row)
        {
            result[rowIdx, colIdx++] = col;
        }
        rowIdx++;
    }

    return result;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer, interesting linq usage! I will probably stay with my original code to preserve readability, but good to see how linq is powerful.
2

LINQ was intended to process and produce collections rather than multidimensional arrays. You can replace the first for loop with some LINQ that's a little more expressive, but you can't really get away from using for loops for repopulating the new array:

public static string[,] SkipBlankRows(this string[,] array2D)
{
    var columns = array2D.GetLength(1);
    var rows = array2D.GetLength(0);
    var temp = Enumerable.Range(0, rows)
        .Select(i => Enumerable.Range(0, columns).Select(j => array2D[i, j]).ToList())
        .Where(row => !row.All(string.IsNullOrEmpty))
        .ToList();

    string[,] result = new string[temp.Count, columns];
    rows = temp.Count;

    for (int r = 0; r < rows; r++)
    {
        var row = temp[r];
        for (var c = 0; c < row.Count; c++)
        {
            result[r, c] = row[c];
        }
    }
    return result;
}

Of course, if you're willing to bring in a couple of helper methods to abstract away the conversion to and from rows, you can end up with a highly efficient and very easy-to-read code.

1 Comment

Thank you for your answer, interesting linq usage! I will probably stay with my original code to preserve readability, but good to see how linq is powerful.
1

It depends on what you want your output to look like, do you just want to skip over the blank strings and have a list of values? Or do you want your data to still be in the multidimensional array?

If your answer to this question is "the second one" then your code is fine.

If you just want a list of all of the values out of the multi-dimentional array you could write something like:

public static IEnumerable<string> SkipBlankRows(this string[,] array2D)
{
    return (from string s in array2D where !string.IsNullOrWhiteSpace(s) select s);
}

This returns a flat structure of values from the array.

1 Comment

Thanks for your answer! I want just to remove (skip) blank rows and return the 2D array of string.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.