Searching a two dimensional object array in c# - c#

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?

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;
}

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

Related

Count non null elements in an array of lists

I couldn't find this anywhere else.
I've an array of lists:
public List<xmldata>[] XMLArrayList = new List<xmldata>[9999];
To initialize and insert a list into each position, i do the following:
for(int m=0; m< XList.XMLArrayList.Count(); m++)
{
XList.XMLArrayList[m] = new List<xmldata>();
}
But i would like to count how many elements there aren't null.
EX: Positions 0 to 5 have a List on them. But other positions not.
Tried a linq approach:
int count = XList.XMLArrayList.Count(x => x != null);
But it returns me the array size (9999). How can i count the non null elements on an array of lists ?
Ps: Already tried Dictionary and And List of List - this approach works best for achieving what i need.
Thanks.
Try this:
int count = XList.XMLArrayList.Count(x => x.Count()>0);
you can also do this
XList.XMLArrayList.Where(x => x.Any()).Count();

Transfer specific datatable contents to another array

I'm trying to transfer my datatable contents to another array. I am only going to get specific fields from the datatable, but I do not know how to save the specific columns content to another array.
What I did:
dr = SuperViewBLL.GetSomeStuff();
string[] new_array;
if (dr.Rows.Count > 0)
{
for (int i = 0; i < dr.Rows.Count;i++ )
{
new_array[i] = dr.Rows[i]['StuffLocationId'];
// I do know this is wrong
}
}
How can I get the column StuffLocationId to the array new_array?
That line is almost right, except that you need double quotes rather than single and you also need to cast/convert the value to type String to put it into a String array:
new_array[i] = (string) dr.Rows[i]["StuffLocationId"];
or, if the data is nullable:
new_array[i] = dr.Rows[i]["StuffLocationId"] as string;
The issue is that the array doesn't exist because you haven't created it. In order to create an array you have to know the size. If you haven't specified a size, either implicitly or explicitly, then you haven't created an array. This:
string[] new_array;
should be this:
string[] new_array = new string[dr.Rows.Count - 1];
You can also throw a bit of LINQ at the problem and succinctify the code a bit:
var new_array = dr.AsEnumerable()
.Select(row => row["StuffLocationId"] as string)
.ToArray();
That's also an example of specifying the size of the array implicitly.
This way is much more clear:
dt = SuperViewBLL.GetSomeStuff();
List<string> list = new List<string>();
foreach(DataRow row in dt.Rows)
{
list.Add((!row.IsNull("StuffLocationId") ? row["StuffLocationId"] as string : string.Empty));
}
Updated with the help of #jmcilhinney

sorting List<string[]> by many columns

I have List which I would like to sort by many columns. For example, string[] has 5 elements (5 columns) and List has 10 elements (10 rows). For example I would like to start sorting by 1st column, then by 3rd and then by 4th.
How could it be done in the easiest way with C#?
I thought about such algorithm:
Delete values corresponding to those columns that I don't want to use for sorting
Find for each of columns that are left, the longest string that can be used to store their value
Change each row to string, where each cell occupies as many characters as there is maximum number of characters for the value for the given column
Assign int with index for each of those string values
Sort these string values
Sort the real data, with help of already sorted indices
But I think this algorithm is very bad. Could you suggest me any better way, if possible, that uses already existing features of C# and .NET?
List<string[]> list = .....
var newList = list.OrderBy(x => x[1]).ThenBy(x => x[3]).ThenBy(x => x[4]).ToList();
Something like this:
var rows = new List<string[]>();
var sortColumnIndex = 2;
rows.Sort((a, b) => return a[sortColumnIndex].CompareTo(b[sortColumnIndex]));
This will perform an in-place sort -- that is, it will sort the contents of the list.
Sorting on multiple columns is possible, but requires more logic in your comparer delegate.
If you're happy to create another collection, you can use the Linq approach given in another answer.
EDIT here's the multi-column, in-place sorting example:
var rows = new List<string[]>();
var sortColumnIndices = new[] { 1, 3, 4 };
rows.Sort((a, b) => {
for (var index in sortColumnIndices)
{
var result = a[index].CompareTo(b[index]);
if (result != 0)
return result;
}
return 0;
});

How many elements of array are not null?

An array is defined of assumed elements like I have array like String[] strArray = new String[50];.
Now from 50 elements only some elements are assigned and remaining are left null then I want the number of assigned elements.
Like here only 30 elements are assigned then I want that figure.
You can use Enumerable.Count:
string[] strArray = new string[50];
...
int result = strArray.Count(s => s != null);
This extension method iterates the array and counts the number of elements the specified predicate applies to.
Using LINQ you can try
int count = strArray.Count(x => x != null);
Use LINQ:
int i = (from s in strArray where !string.IsNullOrEmpty(s) select s).Count();

Perserving Array from AnonymousType

I looked online for some references but didn't have too much luck. Hopefully it's just some simple thing I'm overlooking, but in my code I'm looping through the participant list and storing the queried results into the array. As you can tell, my foreach statement will just add the last element of the array since the first one is replaced.
How can I just add the value to the next array index. So, if there are [2] in the array, how can I make sure that this.physEntityPhysicalLeftEntityIDs contains [2] instead of just always [1]? If I need to clarify, let me know.
if (leftParticipants.Length >= 0) // Check to see if LeftParticipants exists
{
for (int c = 0; c < leftParticipants.Length; c++)
{
var l_entityIDs =
from BioList in o_data.Descendants(bp + "physicalEntityParticipant")
where BioList.Attribute(rdf + "ID").Value == leftParticipants[c].TrimStart('#')
select new
{
o_entityIDs = BioList.Elements(bp + "PHYSICAL-ENTITY")
.Select(entityID => entityID.Attribute(rdf + "resource").Value).ToArray()
};
foreach (var entity in l_entityIDs)
{
this.physEntityPhysicalLeftEntityIDs = entity.o_entityIDs; // Set SmallMolecules from Left
}
}
}
If physEntityPhysicalLeftEntityIDs is an array, you'll need to initialize an index variable and increment it each time through the foreach loop:
int destIndex = 0;
foreach (var entity in l_entityIDs)
{
this.physEntityPhysicalLeftEntityIDs[destIndex] = entity.o_entityIDs; // Set SmallMolecules from Left
++destIndex;
}
That assumes that you've allocated enough space in the array. If there are more items than will fit in the array, you're going to get an index out of bounds error.
To make sure there's enough space in the array, you can allocate it before the loop above:
this.physEntityPhysicalLeftEntityIds = new int[l_entityIDs.Count()];
Replace int in that line with the proper type (you didn't say what type is being stored in the array).
Well if you want to treat it like an array/list, all you have to do is
l_enityIDs.ToList()
and then .Add(new {o_entityIDs = foo})
If you want to add it to the IEnumerable, that requires an extension method that returns everything in the source enumberable, and a yield statement adding on your next value.

Categories