Why the indexing affects a complete array instead of one item ? (c#) - c#

I have faced with a strange behavior in c#. I created a int[][] array like this:
int[][] m_dist = Enumerable.Repeat(Enumerable.Repeat(-1, m.Length).ToArray(), m.Length).ToArray();
Array looks like this:
-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,
Later on when I tried to modify a single array element I was supraised because not only one item was changed but a complete int[] array:
m_dist[1][1] = 0;
Output was:
-1,0,-1,-1,-1,-1,
-1,0,-1,-1,-1,-1,
-1,0,-1,-1,-1,-1,
-1,0,-1,-1,-1,-1,
-1,0,-1,-1,-1,-1,
-1,0,-1,-1,-1,-1,
I suspected that something happens during the array creation therefore I simplified it like this:
//int[][] m_dist = Enumerable.Repeat(Enumerable.Repeat(-1, m.Length).ToArray(), m.Length).ToArray();
int[][] m_dist = new int[m.Length][];
for (int i = 0; i < m_dist.Length; i++)
{
m_dist[i] = new int[m.Length];
for (int j = 0; j < m_dist[i].Length; j++)
{
m_dist[i][j] = -1;
}
}
With this kind of initialization the addressing was flawless.
Of course I can live with this solution, but I would like to understand what happened during my first attempt.
If somebody could explain that would be great!
Debug code:
int[][] m_dist = Enumerable.Repeat(Enumerable.Repeat(-1, m.Length).ToArray(), m.Length).ToArray();
for (int i = 0; i < m_dist.Length; i++)
{
for (int j = 0; j < m_dist[i].Length; j++)
{
Console.Write(m_dist[i][j] + ",");
}
Console.Write("\n");
}
Console.WriteLine();
m_dist[1][1] = 0;
for ( int i = 0; i< m_dist.Length; i++ )
{
for (int j = 0; j < m_dist[i].Length; j++)
{
Console.Write(m_dist[i][j] + ",");
}
Console.Write("\n");
}
Console.WriteLine();
Of course I can live with this solution, but I would like to understand what happened during my first attempt.If somebody could explain that would be great!

Let me unpack this line so you can see what exactly happens:
int[][] m_dist = Enumerable.Repeat(Enumerable.Repeat(-1, m.Length).ToArray(), m.Length).ToArray();
Unrolling the expressions we get:
int[] array = Enumerable.Repeat(-1, m.Length).ToArray();
int[][] m_dist = Enumerable.Repeat(array, m.Length).ToArray();
You create a single array filled with -1 values, and then create an array m_dist that contains repeated references to that array. Every entry in m_dist points to array, so editing an element through any of these references is reflected through all of those references.
What you want to do is create m.Length separate arrays:
int[][] m_dist = Enumerable.Range(0, m.Length)
.Select(_ => Enumerable.Repeat(-1, m.Length).ToArray())
.ToArray();

Related

How can i write which element corresponds to which score in 2 different arrays?

I have got 25 elements in my txt file. My code calculates their scores according to answer key. Then i would like to sort them without using sort.Array etc. I made it and a assigned them another array which is name is result. Now i would like to write the elements number according to order of result array
. For example the element 101' score 78. The element 105' s score is 25.
The result array sort them: 78-25
i would like to sort them : 101-105
my code is:
//arranging results according to their values
int temp = 0;
int[] elm = new int[result.Length];
for (int i = 0; i <= result.Length-1 ; i++)
{
for (int j = i+1 ; j < result.Length; j++)
{
if (result[i] < result[j])
{
temp = result[i];
result[i] = result[j];
result[j] = temp;
}
elm[j] = Convert.ToInt16(row[i,0]);
}
;
}

Jagged 2D Array

I'm trying to create an array with the following structure
D
C C
B B B
A A A A
Which will be N x N but split diagonally. Initially, all I know is the bottom row essentially just:
string[,] table = new string[n,];
How can I build on this structure so that when I get to the next row I can declare how many elements it has? Would it be something along the lines of:
for(int i = 0; i <= n; i++) {
table[i] = new string[--n]
}
The [,] syntax creates multidimensional arrays, not jagged arrays. For the latter, you would need to do this:
int n = 4;
string[][] table = new string[n][];
for (int i = 0; i < n; i++)
table[i] = new string[n-i];
Btw. you really don’t want to decrement n while looping in a loop with the condition i < n (or i <= n).

How do I initialize a list of integer arrays in C#?

I need to create a list of integer arrays. I know ahead of time the length of the arrays, but I don't know how many of them need to be added to the list.
I've tried the following code:
List<int[]> MyListOfArrays = new List<int[]>();
int[] temp = new int[30];
range = xlApp.get_Range("NamedRange");
values = (object[,])range.Value2;
for (int i = 0; i < values.GetLength(0); i++)
{
for (int j = 0; j < values.GetLength(1); j++)
{
temp[j] = Convert.ToInt32(values[i + 1, j + 1]);
}
MyListOfArrays.Add(temp);
}
The temp array is filled just fine. However, MyListOfArrays just ends up with the last iteration of temp repeated for all of the entries. Where am I going wrong?
When you add the temp array to the List, it is just a pointer to the array created on the heap. You need to create a new temp array for every array you add to the list.
List<int[]> MyListOfArrays = new List<int[]>();
range = xlApp.get_Range("NamedRange");
values = (object[,])range.Value2;
for (int i = 0; i < values.GetLength(0); i++)
{
int[] temp = new int[30]; // moved inside the loop
for (int j = 0; j < values.GetLength(1); j++)
{
temp[j] = Convert.ToInt32(values[i + 1, j + 1]);
}
MyListOfArrays.Add(temp);
}
Here's the easiest fix.
Your code:
List<int[]> MyListOfArrays = new List<int[]>();
int[] temp = new int[30];// <-- Move this inside the 'i' for-loop.
range = xlApp.get_Range("NamedRange");
values = (object[,])range.Value2;
for (int i = 0; i < values.GetLength(0); i++)
{
for (int j = 0; j < values.GetLength(1); j++)
{
temp[j] = Convert.ToInt32(values[i + 1, j + 1]);
}
MyListOfArrays.Add(temp);
}
Do this instead:
List<int[]> MyListOfArrays = new List<int[]>();
range = xlApp.get_Range("NamedRange");
values = (object[,])range.Value2;
for (int i = 0; i < values.GetLength(0); i++)
{
int[] temp = new int[30]; //<-- This will create a new array of ints, with each iteration of 1.
for (int j = 0; j < values.GetLength(1); j++)
{
temp[j] = Convert.ToInt32(values[i + 1, j + 1]);
}
MyListOfArrays.Add(temp);
}
You just need to move the line:
int[] temp = new int[30];
immediately after:
for (int i = 0; i < values.GetLength(0); i++) {
so it initializes to a new array at each iteration of the loop.
MyListOfArrays.Add is adding the same reference to you list for each iteration of i, and it overwrites the values in temp[] each time. So you end up with the values of the last iteration repeated.

C# Multi-dimensional Array

I'm trying to build a multi-dimensional array to store integer arrays.
Array[] TestArray = new Array[2];
for(int i = 0; i < TestArray.Length; i++)
{
TestArray[i] = new int[5];
}
How do I go about accessing the newly created members of the Array? I am not sure how to access the newly created arrays in the array although I can see that they're properly created and stored when debugging in Visual Studio.
If you want an array of integer arrays, then you should declare it as such:
int[][] testArray = new int[2][];
for(int i = 0; i < testArray.Length; i++)
{
testArray[i] = new int[5];
}
Arrays of arrays are called Jagged Arrays (in contrast to Multidimensional Arrays).
Here is how to access fourth item in the second array:
int value = ((int[]) TestArray.GetValue(1))[3];
Although you would have much less trouble working with jagged arrays:
int[][] TestArray = new int[2][];
for (int i = 0; i < TestArray.Length; i++)
{
TestArray[i] = new int[5];
}
or multidimensional arrays:
int[,] TestArray = new int[2,5];
Cast the TestArray element as an int[].
Array[] TestArray = new Array[2];
for(int i = 0; i < TestArray.Length; i++)
{
TestArray[i] = new [] { 2,3 };
}
var firstIndexOfFirstArray = ((int[])TestArray[0])[0];
T[][] is the syntax you are looking for.
int[][] test = new int[2][]; //Declaring the array of arrays.
for (int i = 0; i < test.Length; i++)
{
test[i] = new int[5]; //Instantiating a sub-arrays.
for (int x = 0; x < test[i].Length; x++)
test[i][x] = x + i; //Filling a sub-arrays.
}
foreach (var array in test) //iterating over the array of arrays.
Console.WriteLine("Array: " + string.Join(", ", array)); //using a sub-array
Console.ReadLine();
For more info: http://msdn.microsoft.com/en-us/library/2s05feca.aspx
If looking for integer array, try
int[][] testArray

Initializing two dimensional array of objects

I have a 2-dimensional array of objects, which I initialize using the traditional loop:
PairDS[,] tempPb1 = new PairDS[LoopCounterMaxValue+1, LoopCounterMaxValue+1];
for (int i = 0; i <= LoopCounterMaxValue; i++)
for (int j = 0; j <= LoopCounterMaxValue; j++)
tempPb1[i, j] = new PairDS();
Is there any better way to do this using Enumerable or something?
I thought Initialize could do it, but it only works with value types.
int N = 10;
PairDS[,] temp = new PairDS[N + 1, N + 1];
temp.Initialize();
What I recommend you do is use a jagged array.
class PairDS { public PairDS(int row, int col) { } }
static void Main(string[] args)
{
int N = 10;
PairDS[][] temp = Enumerable.Range(0, N + 1).Select(
(row) => Enumerable.Range(0, N + 1).Select(
(col) => new PairDS(row, col)).ToArray()).ToArray();
}
I don't believe you can represent a multi-dimensional array as an Enumerable or List, directly because it (the CLR) has no way of knowing how you intend to index the array.
If you did work it out row by row, it'd actually be worse (ie slower) then simply looping through the array as you're doing and initializing each cell.
There's no way to directly initialize a 2D array with the Enumerable types and as some users have pointed out there's nothing directly wrong with what you're doing. If you're just looking to simplify the loop though this might be what you're looking for;
const int length = LoopCounterMaxValue + 1;
PairDS[,] tempPb1 = new PairDS[length, lenth];
for (var i = 0; i < length * length; i++) {
var column = i % length;
var row = (i - column) / length;
tempPb1[row, column] = new PairDS();
}

Categories

Resources