Jallrich
Jallrich

Reputation: 469

How can I check if a multidimensional array has a value and its index?

I have a multidimensional array:

string[,] array = new string[,]
{
    {"cat", "dog", "plane"},
    {"bird", "fish", "elephant"},
};

And I want to identify if it contains a value, and if so, I need its index, let's say, for "bird".

What I need is

So, If I say "bird" I want it to give me a random string between "fish" and "elephant". If it were a normal array I would make a simple

random.Next(1, array.Length);

But, I don't know how to make it with a 2D array.

Thanks!

Upvotes: 1

Views: 25280

Answers (4)

romain-aga
romain-aga

Reputation: 1561

Here an example without breaking your data structure:

static int IndexOf<T>(T[,] array, T toFind)
    {
        int i = -1;
        foreach (T item in array)
        {
            ++i;
            if (toFind.Equals(item))
                break ;
        }
        return i;
    }

    static string GetRandomString(string[,] array, string toFind)
    {
        int lineLengh = array.Length / array.Rank;
        int index = IndexOf(array, toFind);
        int lineIndex = index / lineLengh;

        Random random = new Random();
        index = random.Next(lineIndex * lineLengh + 1, (lineIndex + 1) * lineLengh);
        return array[lineIndex, index % lineLengh];
    }

    // If you want to get a random element between the index and the end of the line
    // You can replace "bird" by any word you want,
    // except a word at the end of a line (it will return you the first element of the next line)
    // static string GetRandomString(string[,] array, string toFind)
    // {
    //     int lineLengh = array.Length / array.Rank;
    //     int index = IndexOf(array, toFind);

    //     Random random = new Random();
    //     index = random.Next(index + 1, (index / lineLengh + 1) * lineLengh);
    //     return array[index / lineLengh, index % lineLengh];
    // }

    static void Main(string[] args)
    {
        string[,] array = new string[,]
        {
            {"cat", "dog", "plane"},
            {"bird", "fish", "elephant"},
        };
        Console.WriteLine(GetRandomString(array, "bird"));
        Console.ReadKey();
    }

To be perfect, you should add a check if the index is not -1 and if you can get a random number from the range between the index and the end of the line.


You should also use string[][], if your multidimensionnal array can contain lines with different sizes. With string[,], your array has to contain line with the same size.

Upvotes: -1

Theo Yaung
Theo Yaung

Reputation: 4054

Here's an example of doing what you want with multi-dimensional arrays. Note that in the comment there's an edge case you'll need to handle.

using System;

class Program
{
    static string[,] array = new string[,]
    {
        { "cat", "dog", "plane" },
        { "bird", "fish", "elephant" },
    };

    static int FindRow(string elem)
    {
        int rowCount = array.GetLength(0),
            colCount = array.GetLength(1);
        for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
        {
            for (int colIndex = 0; colIndex < colCount; colIndex++)
            {
                if (array[rowIndex, colIndex] == elem)
                {
                    return rowIndex;
                }
            }
        }
        return -1;
    }

    static string PickRandomTail(int rowIndex)
    {
        int colCount = array.GetLength(1);
        int randColIndex = new Random().Next(1, colCount);
        return array[rowIndex, randColIndex];
    }

    static void Main()
    {
        int rowIndex = FindRow("bird");
        if (rowIndex < 0)
        {
            // handle the element is not found
        }
        Console.WriteLine(PickRandomTail(rowIndex));
    }
}

Upvotes: 2

Enigmativity
Enigmativity

Reputation: 117175

A List<list<string>> would be easier to work with.

If I start with your original data I would do this to nest it in a list:

List<List<string>> nested =
    array
        .OfType<string>()
        .Select((x, i) => new { x, i })
        .GroupBy(x => x.i / array.GetLength(1), x => x.x)
        .Select(x => x.ToList())
        .ToList();

Now I can write this function:

var random = new Random();
Func<string, string> getRandom = x =>
(
    from row in nested
    where row[0] == x
    from choice in row.Skip(1).OrderBy(y => random.Next())
    select choice
).FirstOrDefault();

Calling it with getRandom("bird") correctly gives me either "fish" or "elephant".

Upvotes: 1

Grant Winney
Grant Winney

Reputation: 66501

You need to use array.GetLength() instead of array.Length, to get the length of a single dimension of your multi-dimensional array.

Iterate through the array. If you find a match, store the current index and grab a random value from the matching row, using array.GetLength and the Random class.

Random rnd = new Random();

int index = -1;
string randomWord = "";

for(int i = 0; i < array.GetLength(0); i++)
{
    if (array[i,0] == "bird")
    {
        index = i;
        randomWord = array[i,rnd.Next(1, array.GetLength(1))];
        break;
    }
}

Upvotes: 2

Related Questions