Questions about 2D lists C# - c#

I've ran into an issue with lists as I need to create a 2-dimensional list where I can read data by giving the columns and rows, so I could read from my list by using my_List[col][row] so is it possible making a 2D list that way?
How much performance impact can this have and anything I should be aware that could have a performance impact on the code? I might need to read a few hundred times per second from my 2D list
Is it possible to have a more grid type 2D list so if i have data in 3, 4 and 5 but i dont have anything in 0, 1, and 2 think of it like coordinates. so can I read from the list using myList[3][5] and get the data from there with 0, 1 and 2 having nothing? or do i need to loop it through and add something there like null?
thanks in advance!

Yes, you can indeed use multidimensional arrays or jagged arrays for storing "2D data".
As for creating a data structure that doesn't use any memory space for unused indexes, an option could be to use a dictionary where the keys are tuples of two numbers, like this (assuming that your data are strings):
var items = new Dictionary<(int, int), string>();
items.Add((0,1), "0-1"); //this throws an error if the key already exists
items[(2,3)] = "2-3"; //this silently replaces the value if the key already exists
Console.WriteLine(items.Keys.Contains((0,1))); //true
Console.WriteLine(items.Keys.Contains((0,2))); //false
Console.WriteLine(items[(2,3)]); //"2-3"
Of course you probably want to encapsulate this functionality in its own class, but you get the idea.
Note however that this dictionary approach will probably be worse than a plain array in terms of performance, but it's up to you to experiment and collect some metrics.

You can create 2D Arrays like this :
string[,] twoDArray = new string[2,2];
Then you can loop through it like :
for (int i = 0; i < twoDArray.Length; i++)
{
foreach (int j in twoDArray[i,0])
{
}
}
You can also create 2D Lists like this:
List<List<string>> grid = new List<List<string>>();
and iterate through them using an Enumerator and for example a for loop:
var enu = grid.GetEnumerator();
while (enu.MoveNext())
{
for(int i = 0; i < enu.Current.Count; i++)
{
enu.Current.RemoveAt(i);
}
}
You are basically iterating over all lists and then through each list as long as its size is. Inside the for loop you can alter the encapsuled lists in whatever way you like.

Related

c# - How to create 2D array with unknown number of rows, but known number of columns?

I am trying to create 2-dimensional array of ints with two columns, but an unknown amount of rows. I know that in order to create the 2D array itself I do the following:
List<List<int>> myList = new List<List<int>>();
But how do I modify this to specify the number of columns? And how would I add a row to this array?
You could use a List of int arrays. The List would represent the rows, and each int array in the List would be one row. The length of each array would equal the amount of columns.
List<int[]> rows = new List<int[]>();
int[] row = new int[2];
row[0] = 100;
row[1] = 200;
rows.Add(row);
As long as each int array is length two (int[] row = new int[2]), all rows will have two columns. The List can have any number of int arrays added to it in this way.
There is no way to create 2D array (or any other sort of array) with unknown number of elements. Once you initialize it you have to provide number of elements.
The syntax for multidimensional array is the following:
var arr = new int[k, l, n,...]
You can create so called jagged array, i.e. array of arrays and initialize it in the cycle. You will still need to initialize it with a number of subarrays and then fill with those subarrays of given lengths:
var arr = new int[][n];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = new int[subArrayLength];
}
What you actually do is List of Lists which can have any number of "rows" of any length. You can add new list of specific length to an outer list by List method Add() and the same way you can add an element to any of inner List.
So basically to add a "row" you would need the following:
List<List<int>> table = new List<List<int>>();
table.Add(Enumerable.Repeat(defaultValue, numberOfColumns).ToList());
To add a column you would need something like this:
foreach (var row in table)
{
row.Add(defaultValue);
}
It seems that you want to simulate table structure - for that I would suggest to create a class to incapsulate table logic from above inside so that any addition of row will cause addition of outer List of current numberOfColumns size and addition of column will cause addition of an element to all outer lists.
However if you need a fixed number of columns the best alternative you can use is to declare a new class with your columns mapped to the properties of the class and then simply declare a List like it is described in the following answer as #shash678 pointed
Original answer: Consider using a List<Tuple<int, int>>.
Explanation: To begin with, an int[] is not a List<>. From the spirit of your question you seem to have the need to group several units of data together with a finite size, like a records in a table. You could decide to create a POCO with a more descriptive name (which would increase code readability and help with semantics), use an array of fixed size, or use a Tuple. Since there is no mention as to the need for mutability, and the size of the inner "array" will be fixed, I would suggest a Tuple. Through type safety you will ensure that the size and shape of each new object added to the list of Tuples is correct.
Your fist and second questions would be taken care, as far as the 3rd, see: Tuple Pair
e.g. list.Add(Tuple.Create<int,int>(1,1));
I feel like these answers are leading you down a bad path. When learning how to program, you should also consider best practices. In this case your code is what you should use. If you can avoid setting explicit array size, you should(In my opinion). List were create for this purpose. This sample app explains how to use the list correctly in this scenario. My personal opinion is to avoid using arrays if you can.
int someNumberOfRow = 10;//This is just for testing purposes.
Random random = new Random();//This is just for testing purposes.
List<List<int>> myList = new List<List<int>>();
//add two elements to the an arraylist<int> then add this arraylist to myList arraylist
for(int i = 0; i < someNumberOfRow; i++)
{
//Create inner list and add two ints to it.
List<int> innerList = new List<int>();
innerList.Add(random.Next());
innerList.Add(random.Next());
//Add the inner list to myList;
myList.Add(innerList);
}
//This prints myList
for(int i = 0; i < myList.Count; i++)
{
Console.WriteLine((i + 1) + ": " + myList[i][0] + " - " + myList[i][1]);
}
Console.WriteLine("\n\n");
//If the app may scale in the future, I suggest you use an approach similar to this
foreach(List<int> sublist in myList)
{
foreach(int columns in sublist)
{
Console.Write(columns + " ");
}
Console.WriteLine();
}
Console.ReadLine();

C# arrays, how to create empty array?

I'm learning c#, with my primary language before now being php. I was wondering how (or if) you could create an empty array in c#.
In php, you can create an array, and then add any number of entries to it.
$multiples=array();
$multiples[] = 1;
$multiples[] = 2;
$multiples[] = 3;
In c#, I'm having trouble doing something similar:
int[] arraynums = new int[];
arraynums[] = 1;
arraynums[] = 2;
arraynums[] = 3;
Which gives the error "array creation must have array size or array initializer." If I don't know how many entries I want to make, how do I do this? Is there a way around this?
If you don't know the size in advance, use a List<T> instead of an array. An array, in C#, is a fixed size, and you must specify the size when creating it.
var arrayNums = new List<int>();
arrayNums.Add(1);
arrayNums.Add(2);
Once you've added items, you can extract them by index, just like you would with an array:
int secondNumber = arrayNums[1];
c# arrays have a static size.
int[] arraynums = new int[3];
or
int[] arraynums = {1, 2, 3}
if you want to use dynamic sized array, you should use ArrayList, or List.
I would recommend using a different collection such as a List<T> or a Dictionary<TKey, TValue>. Calling the collection in PHP an array is just a misnomer. An array is a continuous fixed size block of memory that contains only a single type and offers direct access by calculating the offset for a given index. The data type in PHP does none of these things.
Examples;
List<int> my_ints = new List<int>();
my_ints.Add(500);
Dictionary<string, int> ids = new Dictionary<string, int>();
ids.Add("Evan", 1);
int evansId = ids["Evan"];
Examples of when to use an array;
string[] lines = File.ReadAllLines(myPath);
for (int i = 0; i < lines.Length; i++)
// i perform better than other collections here!
Newer way, since .NET 4.6 / Core 1.0, in case somebody hits this:
System.Array.Empty<T>() method.
This is more efficient if called multiple times, as it's backed by a single static readonly array generated at compile time.
https://learn.microsoft.com/en-us/dotnet/api/system.array.empty
https://referencesource.microsoft.com/#mscorlib/system/array.cs,3079
Try this post: Dynamic array in C#. It has a couple of links in the first answer that show alternate ways of indexing data. In C#, there is no way of making dynamic arrays but those links show some workarounds.

Simple Dictionary Lookup is Slow in .Net Compared to Flat Array

I found that dictionary lookup could be very slow if compared to flat array access. Any idea why? I'm using Ants Profiler for performance testing. Here's a sample function that reproduces the problem:
private static void NodeDisplace()
{
var nodeDisplacement = new Dictionary<double, double[]>();
var times = new List<double>();
for (int i = 0; i < 6000; i++)
{
times.Add(i * 0.02);
}
foreach (var time in times)
{
nodeDisplacement.Add(time, new double[6]);
}
var five = 5;
var six = 6;
int modes = 10;
var arrayList = new double[times.Count*6];
for (int i = 0; i < modes; i++)
{
int k=0;
foreach (var time in times)
{
for (int j = 0; j < 6; j++)
{
var simpelCompute = five * six; // 0.027 sec
nodeDisplacement[time][j] = simpelCompute; //0.403 sec
arrayList[6*k+j] = simpelCompute; //0.0278 sec
}
k++;
}
}
}
Notice the relative magnitude between flat array access and dictionary access? Flat array is about 20 times faster than dictionary access ( 0.403/0.0278), after taking into account of the array index manipulation ( 6*k+j).
As weird as it sounds, but dictionary lookup is taking a major portion of my time, and I have to optimize it.
Yes, I'm not surprised. The point of dictionaries is that they're used to look up arbitrary keys. Consider what has to happen for a single array dereference:
Check bounds
Multiply index by element size
Add index to pointer
Very, very fast. Now for a dictionary lookup (very rough; depends on implementation):
Potentially check key for nullity
Take hash code of key
Find the right slot for that hash code (probably a "mod prime" operation)
Probably dereference an array element to find the information for that slot
Compare hash codes
If the hash codes match, compare for equality (and potentially go on to the next hash code match)
If you've got "keys" which can very easily be used as array indexes instead (e.g. contiguous integers, or something which can easily be mapped to contiguous integers) then that will be very, very fast. That's not the primary use case for hash tables. They're good for situations which can't easily be mapped that way - for example looking up by string, or by arbitrary double value (rather than doubles which are evenly spaced, and can thus be mapped to integers easily).
I would say that your title is misleading - it's not that dictionary lookup is slow, it's that when arrays are a more suitable approach, they're ludicrously fast.
In addition the Jon's answer I would like to add that your inner loop does not do very much, normally you do a least some more work in the inner loop and then the relative performance loss of the dictionary is somewhat lower.
If you look at the code for Double.GetHashCode() in Reflector you'll find that it is executing 4 lines of code (assuming your double is not 0), just that is more than the body of your inner loop. Dictionary<TKey, TValue>.Insert() (called by the set indexer) is even more code, almost a screen full.
The thing with Dictionary compared to a flat array is that you don't waste to much memory when your keys are not dense (as they are in your case) and that read and write are ~O(1) like arrays (but with a higher constant).
As a side note you can use a multi dimensional array instead of the 6*k+j trick.
Declare it this way
var arrayList = new double[times.Count, 6];
and use it this way
arrayList[k ,j] = simpelCompute;
It won't be faster, but it is easier to read.

I need to create 2D array in C#

I need to create 2D jagged array. Think of a matrix. The number of rows is known, the number of columns is not known. For example I need to create array of 10 elements, where type of each element string[]. Why do I need that? The number of columns is not known - this function must simply do the allocation and pass array to some other function.
string[][] CreateMatrix(int numRows)
{
// this function must create string[][] where numRows is the first dimension.
}
UPDATE
I have C++ background. In C++ I would write the following (nevermind the syntax)
double ** CreateArray()
{
double **pArray = new *double[10]() // create 10 rows first
}
UPDATE 2
I was considering using List, but I need to have indexed-access to both rows and columns.
return new string[numRows][];
Cannot be done. However you could do something like this:
List<List<string>> createMatrix(int numRows)
{
return new List<List<string>>(numRows);
}
That allows you to be able to have a flexible amount of objects in the second dimesion.
You can write:
string[][] matrix = new string[numRows][];
and that will produce a 2D array of null elements. If you want to fill the array with non-null items, you need to write:
for (int row = 0; row < numRows; row++)
{
matrix[row] = new string[/* col count for this row */];
}
You need to specify the column count for each row of the matrix. If you don't know it in advance, you can either.
Leave the matrix items unintialised, and populate them as you know their size.
Use a fixed number that will give you room enough for the maximum possible size.
Avoid arrays and use List<> as suggested by others here.
Hope this helps.

How do you initialize a 2 dimensional array when you do not know the size

I have a two dimensional array that I need to load data into. I know the width of the data (22 values) but I do not know the height (estimated around 4000 records, but variable).
I have it declared as follows:
float[,] _calibrationSet;
....
int calibrationRow = 0;
While (recordsToRead)
{
for (int i = 0; i < SensorCount; i++)
{
_calibrationSet[calibrationRow, i] = calibrationArrayView.ReadFloat();
}
calibrationRow++;
}
This causes a NullReferenceException, so when I try to initialize it like this:
_calibrationSet = new float[,];
I get an "Array creation must have array size or array initializer."
Thank you,
Keith
You can't use an array.
Or rather, you would need to pick a size, and if you ended up needing more then you would have to allocate a new, larger, array, copy the data from the old one into the new one, and continue on as before (until you exceed the size of the new one...)
Generally, you would go with one of the collection classes - ArrayList, List<>, LinkedList<>, etc. - which one depends a lot on what you're looking for; List will give you the closest thing to what i described initially, while LinkedList<> will avoid the problem of frequent re-allocations (at the cost of slower access and greater memory usage).
Example:
List<float[]> _calibrationSet = new List<float[]>();
// ...
while (recordsToRead)
{
float[] record = new float[SensorCount];
for (int i = 0; i < SensorCount; i++)
{
record[i] = calibrationArrayView.ReadFloat();
}
_calibrationSet.Add(record);
}
// access later: _calibrationSet[record][sensor]
Oh, and it's worth noting (as Grauenwolf did), that what i'm doing here doesn't give you the same memory structure as a single, multi-dimensional array would - under the hood, it's an array of references to other arrays that actually hold the data. This speeds up building the array a good deal by making reallocation cheaper, but can have an impact on access speed (and, of course, memory usage). Whether this is an issue for you depends a lot on what you'll be doing with the data after it's loaded... and whether there are two hundred records or two million records.
You can't create an array in .NET (as opposed to declaring a reference to it, which is what you did in your example) without specifying its dimensions, either explicitly, or implicitly by specifying a set of literal values when you initialize it. (e.g. int[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };)
You need to use a variable-size data structure first (a generic list of 22-element 1-d arrays would be the simplest) and then allocate your array and copy your data into it after your read is finished and you know how many rows you need.
I would just use a list, then convert that list into an array.
You will notice here that I used a jagged array (float[][]) instead of a square array (float [,]). Besides being the "standard" way of doing things, it should be much faster. When converting the data from a list to an array you only have to copy [calibrationRow] pointers. Using a square array, you would have to copy [calibrationRow] x [SensorCount] floats.
var tempCalibrationSet = new List<float[]>();
const int SensorCount = 22;
int calibrationRow = 0;
while (recordsToRead())
{
tempCalibrationSet[calibrationRow] = new float[SensorCount];
for (int i = 0; i < SensorCount; i++)
{
tempCalibrationSet[calibrationRow][i] = calibrationArrayView.ReadFloat();
} calibrationRow++;
}
float[][] _calibrationSet = tempCalibrationSet.ToArray();
I generally use the nicer collections for this sort of work (List, ArrayList etc.) and then (if really necessary) cast to T[,] when I'm done.
you would either need to preallocate the array to a Maximum size (float[999,22] ) , or use a different data structure.
i guess you could copy/resize on the fly.. (but i don't think you'd want to)
i think the List sounds reasonable.
You could also use a two-dimensional ArrayList (from System.Collections) -- you create an ArrayList, then put another ArrayList inside it. This will give you the dynamic resizing you need, but at the expense of a bit of overhead.

Categories

Resources