Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove Nulls from string[,]

I have a string array defined in c# as

string[,] options = new string[100,3];

Throughout the code it gets populated with data but not always filled.

So if I have 80 parts of it filled and 20 parts of it not filled. The 20 parts have nulls in them or 60 nulls at the end. Is there an easy way to resize the array so that after filling it the array is the same as

String[,] options = new string[80,3];

It would have to be resized based on the position of the first set of 3 nulls it found.

If this was a jagged array I would have done

options = options.Where(x => x != null).ToArray();
like image 224
John Wesley Gordon Avatar asked Mar 16 '23 03:03

John Wesley Gordon


1 Answers

The method is quite long, because it has to check every row twice...

public static string[,] RemoveEmptyRows(string[,] strs)
{
    int length1 = strs.GetLength(0);
    int length2 = strs.GetLength(1);

    // First we count the non-emtpy rows
    int nonEmpty = 0;

    for (int i = 0; i < length1; i++)
    {
        for (int j = 0; j < length2; j++)
        {
            if (strs[i, j] != null)
            {
                nonEmpty++;
                break;
            }
        }
    }

    // Then we create an array of the right size
    string[,] strs2 = new string[nonEmpty, length2];

    for (int i1 = 0, i2 = 0; i2 < nonEmpty; i1++)
    {
        for (int j = 0; j < length2; j++)
        {
            if (strs[i1, j] != null)
            {
                // If the i1 row is not empty, we copy it
                for (int k = 0; k < length2; k++)
                {
                    strs2[i2, k] = strs[i1, k];
                }

                i2++;
                break;
            }
        }
    }

    return strs2;
}

Use it like:

string[,] options = new string[100, 3];
options[1, 0] = "Foo";
options[3, 1] = "Bar";
options[90, 2] = "fiz";
options = RemoveEmptyRows(options);

As suggested by Alexei, there is another way of doing this:

public static string[,] RemoveEmptyRows2(string[,] strs)
{
    int length1 = strs.GetLength(0);
    int length2 = strs.GetLength(1);

    // First we put somewhere a list of the indexes of the non-emtpy rows
    var nonEmpty = new List<int>();

    for (int i = 0; i < length1; i++)
    {
        for (int j = 0; j < length2; j++)
        {
            if (strs[i, j] != null)
            {
                nonEmpty.Add(i);
                break;
            }
        }
    }

    // Then we create an array of the right size
    string[,] strs2 = new string[nonEmpty.Count, length2];

    // And we copy the rows from strs to strs2, using the nonEmpty
    // list of indexes
    for (int i1 = 0; i1 < nonEmpty.Count; i1++)
    {
        int i2 = nonEmpty[i1];

        for (int j = 0; j < length2; j++)
        {
            strs2[i1, j] = strs[i2, j];
        }
    }

    return strs2;
}

This one, in the tradeoff memory vs time, chooses time. It is probably faster, because it doesn't have to check every row twice, but it uses more memory, because it puts somewhere a list of the non-empty indexes.

like image 86
xanatos Avatar answered Mar 30 '23 05:03

xanatos