0

I have declared a two-dimensional object array as

object[,] sectionOpenings = new object[20, 4]; 

The first column is populated with string types, whilst the remaining three columns are all integers.

I wish to do a quick search to find a row with a matching string in the first column and have tried this

var first = Array.Find(sectionOpenings, p => p == "homedepot");

I get the following error:

Error CS0411 The type arguments for method 'Array.Find(T[], Predicate)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

Any suggestions?

Useme Alehosaini
  • 2,998
  • 6
  • 18
  • 26
Jeets
  • 1
  • 1
  • 2
    [Array.Find](https://learn.microsoft.com/en-us/dotnet/api/system.array.find?view=net-5.0) only works on 1-dimensional arrays – greenjaed Dec 22 '20 at 21:36
  • 3
    Instead of using a two dimensional array of disparate types, use a single dimensioned array of objects of a specific type (say a class with a string property and three integer properties). The reason you are getting the error is that the types of the objects in your array are simply `object`. Your predicate (the lambda `p => p == "homedepot"`) doesn't know what to do since `p` is an object and it doesn't have an `operator == (string)`. At the very least (if you want to stay in value type land), use a `List<(string, int, int, int)>` or an array of tuples like that. – Flydog57 Dec 22 '20 at 21:38
  • thank you @greenjaed. – Jeets Dec 22 '20 at 22:09

2 Answers2

1

You can alter your code a bit to get what you what:

var first = Array.Find(sectionOpenings, p => p[0] == "homedepot");

this will look in each array row, the first column p[0] == "homedepot"

edit: my bad, I thought about jagged arrays

Well its not a one liner, but you can create a method like so:

public static int GetMatchingRow(object[,] myArr, string findMe)
{
    for (int i = 0; i < myArr.GetLength(0); i++)
    {
        if (myArr[i, 0] is string && myArr[i, 0] as string == findMe)
            return i;
    }

    return -1;
}
Ziv Weissman
  • 4,400
  • 3
  • 28
  • 61
0

I would suggest changing to a dictionary to ensure type safety- like so:

var sectionOpenings = new Dictionary<string, List<int>>();
sectionOpenings.TryGetValue("homedepot", out var result);

However, if you are stuck using a 2D array, you'll likely have to do this in two steps. One, you'll have to find the matching column. Two, you'll have to retrieve the column. Something like this could work:

object[,] sectionOpenings = new object[20, 4];

var firstRowMatch = Enumerable
     .Range(0, sectionOpenings.GetLength(0)) // Gets row indices
     .Where(row => sectionOpenings[row, 0].ToString().Equals("homedepot"))
     .First();

var result = Enumerable
     .Range(0, sectionOpenings.GetLength(1)) // Gets column indices
     .Select(column => sectionOpenings[firstRowMatch, column])
     .ToArray();

With this example, you will likely have to add some type checks and null checks to make sure that this doesn't explode with a NullReferenceException.

This is adapted from returning a whole column from a 2D array and getting the number of columns/rows from a 2D array on stack overflow.

PS. This assumes you're using System.Linq

Useme Alehosaini
  • 2,998
  • 6
  • 18
  • 26
Airistotal
  • 95
  • 8