I was wondering if there is a way to create a variable number of arrays with certain serialization, for example:
for (int i = 0; i < var; i++)
{
int[] s"i" = new int[var2];
}
for "var" and "var2" = 1, 2, 3, ...
and having as a result, for example if "var" and "var2" = 2, two arrays s1[2] and s2[2].
Is this understandable? is there a way?
C# does not allow for this specific type of behavior as you've described it. However, you do have the option of creating a list containing a variable number of arrays, which essentially accomplishes the same thing with more rigid syntax.
int var = 2;
int var2 = 2;
List<int[]> arrays = new List<int[]>();
for (int i = 0; i < var; i++)
{
arrays.Add(new int[var2]);
}
The end result would be a list containing two arrays, each initialized to a length of two.
Related
This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 1 year ago.
dears ,
i had create a method that will retrieve three arrays after filling them using the ref option
the following error is presented "System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'"
the code as below. how I can fix it
namespace ConsoleApp9
{
class Program
{
public static int getarrays(ref string[] patternName, ref int[] loadindex, ref double[] loadFactor)
{
int status = 0;
for (int i = 0; i < 4; i++)
{
patternName[i] = "test";
}
for (int i = 0; i < 5; i++)
{
loadindex[i] = i;
}
for (int i = 0; i < 8; i++)
{
loadFactor[i] = i/10;
}
return status;
}
static void Main(string[] args)
{
string[] ptt = new string[1];
int[] index = new int[1];
double[] factor = new double[1];
getarrays(ref ptt,ref index, ref factor);
}
}
}
Your arrays all have a size of 1, but your loops go to 4, 5 and 8 respectively. Instead, use the Length property of your arrays in your loops:
for (int i = 0; i < patternName.Length; i++)
{
patternName[i] = "test";
}
This is helpful, because the size of your array is only located in one place (at the creation of the arrays).
You are passing arrays with fixed size of 1. Inside your method, you are iterating for 4, 5 and 8 times while your arrays have length of 1. You should make a constants of pttSize, indexSize and factorSize and use them as arrays size and loops length.
You are passing arrays of length 1 to the function and then try to access indices greater than 0.
Adapt your Main method to pass arrays of the correct length:
string[] ptt = new string[4];
int[] index = new int[5];
double[] factor = new double[8];
Consider I have an Array,
int[] i = {1,2,3,4,5};
Here I have assigned values for it. But in my problem I get these values only at runtime.
How can I assign them to an array.
For example:
I get the max size of array from user and the values to them now how do I assign them to the array int [].
Or can I use anyother data types like ArrayList etc which I can cast to Int[] at the end?
Well, the easiest is to use List<T>:
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
int[] arr = list.ToArray();
Otherwise, you need to allocate an array of suitable size, and set via the indexer.
int[] arr = new int[5];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
This second approach is not useful if you can't predict the size of the array, as it is expensive to reallocate the array every time you add an item; a List<T> uses a doubling strategy to minimize the reallocations required.
You mean?
int[] array = { 1, 2, 3, 4, 5 };
array = new int[] { 1, 3, 5, 7, 9 };
array = new int[] { 100, 53, 25, 787, 39 };
array = new int[] { 100, 53, 25, 787, 39, 500 };
Use List<int> and then call ToArray() on it at the end to create an array. But do you really need an array? It's generally easier to work with the other collection types. As Eric Lippert wrote, "arrays considered somewhat harmful".
You can do it explicitly though, like this:
using System;
public class Test
{
static void Main()
{
int size = ReadInt32FromConsole("Please enter array size");
int[] array = new int[size];
for (int i=0; i < size; i++)
{
array[i] = ReadInt32FromConsole("Please enter element " + i);
}
Console.WriteLine("Finished:");
foreach (int i in array)
{
Console.WriteLine(i);
}
}
static int ReadInt32FromConsole(string message)
{
Console.Write(message);
Console.Write(": ");
string line = Console.ReadLine();
// Include error checking in real code!
return int.Parse(line);
}
}
If you want an array, whose size varies during the execution, then you should use another data structure. A generic List will do. Then, you can dynamically add elements to it.
Edit: Marc posted his answer while I was writing mine. This was exactly what I meant.
You could just use the below line instead of calling a separate function:
using System;
public class Test
{
static void Main()
{
Console.WriteLine("Please enter array size");
int size = Convert.ToInt32(Console.ReadLine());
int[] array = new int[size];
for (int i=0; i < size; i++)
{
Console.WriteLine("Please enter element " + i);
array[i] = Convert.ToInt32(Console.ReadLine());
}
Console.WriteLine("Finished:");
foreach (int i in array)
{
Console.WriteLine(i);
}
}
In Microsoft Visual Studio (Community Edition of course) I have a simple C# program where I declare a simple array without a set size like so
int[] paths;
In a later part of the program I try to set parts of the array but it gives me an error
Use of unsigned local variable 'paths'
in this part of the program
for (int b = 0; b < 100; b++) {
paths[b] = b;
}
In conclusion, I suppose I'm wondering whether this problem that affects just me, or a problem of syntax. (I originated from Java which is half to blame how I ran into this question) I am willing to accept closure on whether this is possible or not,(If so source please) or If I'm just doing it wrong.(If so please provide a solution/suggestions in comments)
In C# Arrays are fixed size, and need to be initialized
var size = 100;
int[] paths = new int[size];
for (var b = 0; b < size; b++) {
paths[b] = b;
}
List is also another good thing for a C# beginner to know about, the difference between an array and a list, is that a List will resize itself for you automagically (I believe there is a very similar List class in Java)
var size = 100;
var paths = new List<int>();
for (var b = 0; b < size; b++) {
paths.Add(b);
}
You just declared the array, but you also need to create it before using it:
paths = new int[100];
You must follow the array declaration syntax.
int[] paths; //-> here you are declaring the paths array and your not creating array.
in memory it set paths array without its sizes. So you must set the size by creating this array as follows.
int[] paths = new int[10];
you can create and declare array like as follows, for to assign another array with it.
EG:
int[] arr1 = new int[] { 0,1,2,3,4,5,6,7};
int[] paths =arr1;
here arr1 size and data will be automatically assigned to paths array.
Firstly you are creating a variable but you have not assigned it at all, this is the reason for you error.
Secondly in C# arrays require a fixed size and can not be resized so when initializing a size must be provided, either explicitly as below or implicitly by initializing it with objects (see comments).
int[] paths; // declaration
paths = new int[100] // assignment, array initialized with a size of 100
// with objects
// paths = new int[] { 1, 2, 3 };
// declaration and assignment can also be merged into 1 line.
// i.e int[] paths = new int[100]
for (int b = 0; b < 100; b++) {
paths[b] = b;
}
you must declare and initialize the array element in your code like
int[] myInt = new int[100]
If you don't know the size before initialize you need to use List like
List<int> list = new List<int>();
list.Add(123);
list.Add(456);
list.Add(789);
Console.WriteLine(list[2]);
and it is necessary to use array and size of array is not fixed before initialize you need to follow below code but below code is wastage of memory usage and more execution process. so my recommend is use List instead of int[]
// Global Variable
int[] myInt;
int mySize = 1;
private void button1_Click(object sender, EventArgs e)
{
if (mySize > 1)
{
int[] tempInt = new int[mySize];
tempInt = myInt;
myInt = new int[mySize];
for (int i = 0; i < mySize - 1; i++)
{
myInt[i] = tempInt[i];
}
myInt[mySize - 1] = mySize;
}
else
{
myInt = new int[mySize];
myInt[mySize - 1] = mySize;
}
mySize++;
}
I need to iterate over an array of arbitrary rank. This is for both reading and writing, so GetEnumerator will not work.
Array.SetValue(object, int) doesn't work on multidimensional arrays.
Array.SetValue(object, params int[]) would require excessive arithmetic for iterating through the multidimensional space. It would also require dynamic invocation to get around the params part of the signature.
I'm tempted to pin the array and iterate over it with a pointer, but I can't find any documentation that says that multidimensional arrays are guaranteed to be contiguous. If they have padding at the end of a dimension then that won't work. I'd also prefer to avoid unsafe code.
Is there an easy way to sequentially address a multidimensional array using only a single index?
Multidimensional arrays are guaranteed to be contiguous. From ECMA-335:
Array elements shall be laid out within the array object in row-major order (i.e., the elements associated with the rightmost array dimension shall be laid out contiguously from lowest to highest index).
So this works:
int[,,,] array = new int[10, 10, 10, 10];
fixed (int* ptr = array)
{
ptr[10] = 42;
}
int result = array[0, 0, 1, 0]; // == 42
You can use the Rank and GetUpperBound property/method to create an indices array that you can pass to the array's SetValue and GetValue methods:
int[] Indices(Array a, int idx)
{
var indices = new int[a.Rank];
for (var i = 0; i < a.Rank; i++)
{
var div = 1;
for (var j = i + 1; j < a.Rank; j++)
{
div *= a.GetLength(j);
}
indices[i] = a.GetLowerBound(i) + idx / div % a.GetLength(i);
}
return indices;
}
..and use it like so:
for (var i = 0; i < array.Length; i++)
{
var indices = Indices(array, i);
array.SetValue(i, indices);
var val = array.GetValue(indices);
}
Perhaps you could join them all into the a single temporary collection, and just iterate over that.
Suppose you have an array like:
double[,] rectArray = new double[10,3];
Now you want the fouth row as a double[] array of 3 elements without doing:
double[] fourthRow = new double[]{rectArray[3,0],
rectArray[3,1],
rectArray[3,2]};
Is it possible someway? Even using a Marshal.Something approach?
Thanks!
You can use Buffer.BlockCopy method:
const int d1 = 10;
const int d2 = 3;
const int doubleSize = 8;
double[,] rectArray = new double[d1, d2];
double[] target = new double[d2];
int rowToGet = 3;
Buffer.BlockCopy(rectArray, doubleSize * d2 * rowToGet, target, 0, doubleSize * d2);
LINQ to the rescue:
var s = rectArray.Cast<double>().Skip(9).Take(3).ToArray();
Explanation: Casting a multi-dimensional array flattens it to a single-dimensional array. After that all we need to do is skip to the element we want (the 4th element in the 2-D array resolves to Skip(9)...) and take 3 elements from it).
Why not make a generic extension method?
public static T[] GetRow<T>(this T[,] input2DArray, int row) where T : IComparable
{
var width = input2DArray.GetLength(0);
var height = input2DArray.GetLength(1);
if (row >= height)
throw new IndexOutOfRangeException("Row Index Out of Range");
// Ensures the row requested is within the range of the 2-d array
var returnRow = new T[width];
for(var i = 0; i < width; i++)
returnRow[i] = input2DArray[i, row];
return returnRow;
}
Like this all you have to code is:
array2D = new double[,];
// ... fill array here
var row = array2D.GetRow(4) // Implies getting 5th row of the 2-D Array
This is useful if you're trying to chain methods after obtaining a row and could be helpful with LINQ commands as well.
You probably want to use a jagged array. That is not an array of 10 by 3 but instead an array of arrays.
Something like :
double[][] rectArray;
....
double [] rowArray = rectArray[3];
There are lots of places to learn more about jagged arrays. For example Dynamically created jagged rectangular array
If you must use a rectangular array and just want to simplify the syntax, you can use a method to get the row like so:
double[] fourthRow = GetRow(rectArray, 3);
public static T[] GetRow<T>(T[,] matrix, int row)
{
var columns = matrix.GetLength(1);
var array = new T[columns];
for (int i = 0; i < columns; ++i)
array[i] = matrix[row, i];
return array;
}
Although this is an old thread, an addition to Joseph Sturtevants answer may be useful. His function crashes in case the matrix's first column is not zero, but another integer.
This is e.g. always the case in case of retrieving data from Excel, like
object[,] objects = null;
Excel.Range range = worksheet.get_Range("A1", "C5");
objects = range.Cells.Value; //columns start at 1, not at 0
The GetRow function could be modified like this:
public static T[] GetRow<T>(T[,] matrix, int row, int firstColumn)
{
var columns = matrix.GetLength(1);
var array = new T[columns];
for (int i = firstColumn; i < firstColumn + columns; ++i)
array[i-firstColumn] = matrix[row, i];
return array;
}