Define a double array without a fixed size? - c#

Hello i have a problem with c# Arrays. I need a array to store some data in there...
My Code is that
double[] ATmittelMin;
ATmittelMin[zaehlMittel] = Gradient(x, xATmax, y, yATmax);
But the compiler says: not defined var
How can i define a double array without a fixed size ?
Thanks a lot!

Arrays are always fixed in size, and have to be defined like so:
double[] items1 = new double[10];
// This means array is double[3] and cannot be changed without redefining it.
double[] items2 = {1.23, 4.56, 7.89};
The List<T> class uses an array in the background and redefines it when it runs out of space:
List<double> items = new List<double>();
items.Add(1.23);
items.Add(4.56);
items.Add(7.89);
// This will give you a double[3] array with the items of the list.
double[] itemsArray = items.ToArray();
You can iterate through a List<T> just as you would an array:
foreach (double item in items)
{
Console.WriteLine(item);
}
// Note that the property is 'Count' rather than 'Length'
for (int i = 0; i < items.Count; i++)
{
Console.WriteLine(items[i]);
}

From what I see you did not declare the zaehlMittel variable. I guess this is what the compiler complains about.
Apart from that, even though you can of course determine the value of that variable programmatically, the moment you want to create an array its size must be known. This is the way arrays work.
In case you cannot do that easily, I suggest using some sort of dynamic datastructure, like a list or a set. Then, once all elements have been added, you are of course still free to create an array from that, as by that time you know the number of elements (even though there are convenience methods like toArray() that will even take care of that).

You have to instanciate the array before using it:
double[] ATmittelMin = new double[10];
ATmittelMin[zaehlMittel] = Gradient(x, xATmax, y, yATmax);

The obvious solution that springs to mind is to use a List:
List<double> ATmittelMin = new List<double>();
ATmittelMin.Add(Gradient(x, xATMax, y, yATMax);
But if you don't want to convert from a list to an array you can grow the array later:
double[] ATmittelMin = new double[10];
// Some code
int index = some_value;
if (index >= TmittelMin.Length)
{
Array.Resize(ATmittelMin, index+5); // So we're not constantly resizing the array
}
It's not ideal as you're doing a lot of the work that List is doing behind the scenes - probably a lot more efficiently than you can.

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.

Determining size of an array of arrays in C#?

I am creating an array of arrays such that:
var arrNewArray = new string[arrOldArray.Length][7];
arrOldArray is an array of arrays such that it's [X][4], meaning the length of the 1st array or "outside" array can change, but the length of the "inside" array is ALWAYS 4, or hold 4 strings ([0][1][2][3]).
Why won't the compiler accept my statement above?
Essentially, I'm trying to take arrOldArray and expand it, or add a few more "columns" by increasing the [4] in the old array to a [7] in the new array and then copy the contents over. Perhaps I'm not doing it the best/efficient way, so any guidance would be appreciated thanks.
I think you want a two dimensional array:
var arrNewArray = new string[arrOldArray.Length, 7];
You would access it like this: arrNewArray[x, y].
This is better than a jagged array, because it clearly communicates that the number of "columns" is the same for every row.
If you want to continue using a jagged array, you need to do it like this:
var arrNewArray = new string[arrOldArray.Length][];
for(int i = 0; i < arrOldArray.Length; ++i)
arrNewArray[i] = new string[7];
The reason for this convoluted way is: With a jagged array, each "row" can have a different number of "columns". A short-hand syntax for the case where each "row" has the same number of "columns" doesn't exist. That's why your code doesn't compile.
A jagged array is essential an array of arrays, so you need to create a new array instance for each "row" of the outer array and explicitly assign it. That's what the for loop is doing.
You can't use Array.Copy with jagged arrays. Each child-array is it's own instance and Array.Copy doesn't make a deep copy, it merely copies the references from one array to another. The effect would be, that both arrays would point to the same items and changing an item in one array would be seen from the other.
You are not creating the jagged array properly. The proper way is to create the first dimension of the jagged array and then loop through the items of the first dimension to create the nested arrays and copy the data from the old arrays. Here's an example:
int newSize = 7;
string[][] newArray = new string[oldArray.Length][];
for (int i = 0; i < oldArray.Length; i++)
{
newArray[i] = new string[newSize];
Array.Copy(oldArray[i], newArray[i], oldArray[i].Length);
}
You would be wanting
var arrNewArray = new string[arrOldArray.Length, 7];
var arrNewArray = new[] {new string[7]};//array of arrays
var arrNewArray = new string[arrOldArray.Length, 7];//two-dimensional array
Using Linq:
int[][] jaggedArray2 = new int[][]
{
new int[] {1,3,5,7,9},
new int[] {0,2,4,6},
new int[] {11,22}
};
int length = jaggedArray.Sum(a => a.Length);
I don't believe what you're asking is directly possible. Because the syntax that you are using is for a jagged array, and what you are doing is effectively asking it to create a multi-dimensional array.
The syntax is confusing since it reads like what you really want is a multi-dimensional array (although I'm aware that's not the case.)
I don't believe you could store your arrays in the newly allocated array either due to a size change. You would need to build a custom copy method to move the data into the larger array.

C# Changing the number of dimensions in an array

Is it possible, in C#, to convert a multi-dimensional array into a 1D array without having to copy all the elements from one to the other, something like:
int[,] x = new int[3,4];
int[] y = (int[])x;
This would allow the use of x as if it were a 12-element 1D array (and to return it from a function as such), but the compiler does not allow this conversion.
As far as I'm aware, a 2D array (or higher number of dimensions) is laid out in contiguous memory, so it doesn't seem impossible that it could work somehow. Using unsafe and fixed can allow access through a pointer, but this doesn't help with returning the array as 1D.
While I believe I can just use a 1D array throughout in the case I'm working on at present, it would be useful if this function was part of an adapter between something which returns a multidimensional array and something else which requires a 1D one.
You can't, it's not possible in C# to convert array's this way. You maybe could do it by using a external dll ( C/C++ ), but then you need to keep your array at a fixed location.
Speed
Generally i would advice to avoid using a 2D array because theese are slow in C#, better use jagged-array or even better single dimensionals with a little bit of math.
Int32[] myArray = new Int32[xSize * ySize];
// Access
myArray[x + (y * xSize)] = 5;
In C#, arrays cannot be resized dynamically. One approach is to use System.Collections.ArrayList instead of a native array. Another (faster) solution is to re-allocate the array with a different size and to copy the contents of the old array to the new array. The generic function resizeArray (below) can be used to do that.
One example here :
// Reallocates an array with a new size, and copies the contents
// of the old array to the new array.
// Arguments:
// oldArray the old array, to be reallocated.
// newSize the new array size.
// Returns A new array with the same contents.
public static System.Array ResizeArray (System.Array oldArray, int newSize) {
int oldSize = oldArray.Length;
System.Type elementType = oldArray.GetType().GetElementType();
System.Array newArray = System.Array.CreateInstance(elementType,newSize);
int preserveLength = System.Math.Min(oldSize,newSize);
if (preserveLength > 0)
System.Array.Copy (oldArray,newArray,preserveLength);
return newArray; }
You can already iterate over a multidim as if it were a 1 dimensional array:
int[,] data = { { 1, 2, 3 }, { 3, 4, 5 } };
foreach (int i in data)
... // i := 1 .. 5
And you could wrap a 1-dim array in a class and provide an indexer property this[int x1, int x2].
But everything else will require unsafe code or copying. Both will be inefficient.
Riding on the back of Felix K.'s answer and quoting a fellow developer:
You can't convert a square to a line without losing information
try
int[,] x = {{1, 2}, {2, 2}};
int[] y = new int[4];
System.Buffer.BlockCopy(x, 0, y, 0, 4);
You cannot cast, you'll have to copy the elements:
int[] y = (from int i in y select i).ToArray();

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