Save and load initial state of an array (int[,]) - c#

I'm trying to save the state of an array so I can load it later in it's initial state. But I don't know how to make them separate instances, and not to reference each other. Here's some sample code:
static void Main(string[] args)
{
int[,] first = new int[5, 5];
int[,] second = first;
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
first[i, j] = i * j;
}
}
first[0, 0] = 10000;
first = second;
Console.WriteLine(first[0, 0]); //10000
}

int[,] second = first;
Means that the second array is a reference to first, they are the same object. You need to create a new array instance. You mention that you want to save the state of the array for later use and for this, you have to copy your original array like so:
int[,] first = new int[5, 5];
int[,] second = new int[5, 5];
Array.Copy(first, second, first.Length);

If you want a separate instance, you need to instantiate it:
int[,] second = new int[5, 5];
Many ways of copying an array can be found here: Any faster way of copying arrays in C#?

first = second
Only copies the reference. You need to copy the elements one by one, just like the way you populate the first array.

Create a shallow copy with Array.Clone()

Related

C#: How to add just the values of a 2D array to a dynamically-sized list? [duplicate]

This question already has answers here:
List items changes as I add new data... why?
(6 answers)
Closed 6 years ago.
I need to create a dynamically sized list that contains pairs of points for a window's form using C#. The list size will change depending on the data that is loaded.
A simplified version of my approach, to simply convey the problem, is as follows (in the real app, the for-loops will iterate over sizes dependent on loaded data):
int[,] dummyInt = new int[1, 2];
List<int[,]> test = new List<int[,]>();
for (int i = 0; i < 100; i++)
{
dummyInt[0, 0] = i;
for (int j = 0; j < 5; j++)
{
dummyInt[0, 1] = j;
test.Add(dummyInt);
}
}
//Show the values in the list for debugging
foreach (int[,] value in test)
{
MessageBox.Show(value.ToString("G"));
}
Using this approach, all 500 values in the list are [99,4].
What I was expecting/hoping to get was
value 1 [0,0]
value 2 [0,1]
...
value 500 [99,4]
Seems like the list is storing the actual variable, and then changing the value with every iteration of the for loop. How can I store just the value of dummyInt as a new object to the list?
I searched for this, but I'm not sure I know the appropriate vocabulary to nail down the search.
Your List object is storing reference to the dummyInt object. If you want to store different values in List you have to create new int array every time you are adding it to List.
Reference:
https://msdn.microsoft.com/en-gb/library/4d43ts61(v=vs.90).aspx
Firstly, you don't need a 2-dimensional array if you're just storing a pair of coordinates. The first coordinate can go in the first element of a 1-dimensional array, and the second coordinate can go in the second element of the array. Secondly, the Clone method can be used to make a copy of an array object if you want to force a separate copy of the whole array to exist.
int[] dummyInt = new int[2];
List<int[]> test = new List<int[]>();
for (int i = 0; i < 100; i++)
{
dummyInt[0] = i;
for (int j = 0; j < 5; j++)
{
dummyInt[1] = j;
test.Add((int[])dummyInt.Clone());
}
}
foreach (int[] value in test)
{
Console.WriteLine("({0},{1})", value[0], value[1]);
}
And finally, an array might not be the best way to store a pair of coordinates. You might want to use a tuple or make your own structure. If you use a Value type (struct) instead of a Reference type (class), you don't need to clone each one.
struct Pair
{
public int x;
public int y;
}
public class Test
{
public static void Main()
{
Pair dummyInt = new Pair();
List<Pair> test = new List<Pair>();
for (int i = 0; i < 100; i++)
{
dummyInt.x = i;
for (int j = 0; j < 5; j++)
{
dummyInt.y = j;
test.Add(dummyInt);
}
}
foreach (Pair value in test)
{
Console.WriteLine("({0},{1})", value.x, value.y);
}
}
}
Note how the result is different if you change the word struct at the beginning to class.

ArgumentsOutOfRangeExeption in a list<T>

Im getting this exeption thrown when the method is invoked. the list contains exactly 52 objects(number of cards).
Any suggestions what may cause it? maybe the Add and RemoveAt Methods? Or maybe the Random?
The compiler also tell the the problem is in deck.Add(temp[j]); line.
public void Shuffle()
{
List<Card> temp = new List<Card>();
Random rand = new Random();
for (int i = 0; i < 52; i++)
{
for (int j = rand.Next(i, 52); j < 52; j++)
{
temp.Add(deck[j]);
deck.RemoveAt(j);
deck.Add(temp[j]);
}
}
}
Ok, let's imagine we are on the first run through the loops. First iteration of both the outer and inner loop. i is 0, and Rand(i, 52) produces 13.
So we have:
i - 0
j - 13
temp - empty list
deck - assume this is a list with 52 elements
Now let's run the three lines of code inside the loop:
temp.Add(deck[j]);
Get the 13th item of deck and add it to temp. Ok, done. temp now has 1 item.
deck.RemoveAt(j);
Remove the 13th item in deck. Ok, fine.
deck.Add(temp[j]);
Get the 13th item in temp and add it to, wait, what?1? temp only has 1 item! Exception! Exception!.
There isn't a need for the temp list in the first place. There is a very good shuffling algorithm that involves going through the original list of items once (not N times). And you just need one temp variable to hold a value while you swap it with another. Like this:
public void Shuffle()
{
Card temp;
Random rand = new Random();
for (int i = deck.Length; i >= 1; i--)
{
int j = rand.Next(0, i + 1);
temp = deck[i];
deck[i] = deck[j];
deck[j] = temp;
}
}
Done.
If you want to shuffle list of items then you can use the following method:
public static void Shuffle<T>(IList<T> arr, Random rnd)
{
for (var i = 0; i < arr.Count; i++)
{
var j = rnd.Next(i, arr.Count);
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
This method will help you shuffle your deck without ArgumentsOutOfRangeExeption
temp[j] does not neccessarily exist. You will need to initialize temp so it has at least j+1 entries or you need to change the line of temp[j] to something more fitting.
When you call rand.Next(i, 52), the result could be 52, which would be out of range for your deck and temporary deck.
Also, you need to initialize your temp list, as #nvoigt points out. List has a constructor that takes an integer for the initial size. You could pass in 52. See: http://msdn.microsoft.com/en-us/library/dw8e0z9z(v=vs.110).aspx.
You could have also easily debugged this yourself by looking at the value of j in your debugger.

Create specific multidimensional array

I have an somewhat basic question regarding multidimensional arrays in C#.
Currently I have the following array:
float[] matrix = new float[16];
I need to create instead a 2D array with each line containing the previously mentioned 16 float numbers. Also, the number of lines in the 2D array is not known at the start of the program (i.e. it will be based on a variable).
How can I create such an array using an efficient data structure?
You could do something like this:
const Int32 arraySize = 16;
var list = new List<float[]>();
Which gives you an empty list containing zero elements (arrays) to start. As you need to add new arrays you would write this:
var array = new float[arraySize];
// do stuff to the array
And then add it to the list:
list.Add(array);
To store 16 float numbers, you could use a 4x4 matrix (which is a 4x4 2-dimensional array). For more details, check out this documentation.
// init the array
float[,] matrix = new float[4,4];
// loop through the array
for(int col = 0; col < matrix.GetLength(0); col++)
for(int row = 0; row < matrix.GetLength(1); row++)
Console.WriteLine(matrix[col, row]);
You can use multidimentional array syntax
float[,] arr2D = new float[12,12];
Alternatively, you could use a loop
float[][] floats = new float[12][];
for(int i=0; i< 12; i++)
{
floats[i] = new float[12];
}

C# Dynamic multidimensional array

I have a function...
private double[,] AddToArray(double[,] array, double[] dataToAdd)
{
// Make a new row at the end of 'array' and copy values
// from 'dataToAdd' into the new row.
//
// Return the new, modified array.
}
However 'double[,]' isn't dynamic and I dont know what the final size of the array will be. I can create a List from it and add the new row to the list, but then I cant seem to convert it back to a double[,]. The List.ToArray() wants to output a jagged array (double[][]). This wont work. I'm interfacing with a program developed in LabVIEW and LV refuses to accept a jagged array. LV is happy with a fixed array ([,]).
Any help?
You could try this:
private double[,] AddToArray(double[,] array, double[] dataToAdd)
{
var dim0 = array.GetLength(0);
var dim1 = array.GetLength(1);
if (dim1 != dataToAdd.Length) throw new ArgumentException();
var na = new double[dim0 + 1, dim1];
Array.Copy(array, na, array.Length);
for (var i = 0; i < dim1; ++i) na[dim0, i] = dataToAdd[i];
return na;
}
It explicitly increments the high-order dimension by one, and also verifies that the length of the low-order dimension is equal to the dataToAdd array. I have not been able to any smarter copying from dataToAdd to the 2D array than by a for loop; it is not possible to apply Array.Copy for different ranked arrays.
You could always create the 2-dimensional array manually:
double[,] array = new double[list.Count, data.Length];
for(int i = 0;i < list.Count;++i)
for(int j = 0;j < data.Length;++j)
array[i, j] = list[i][j];
That is, of course, assuming that all of the 'dataToAdd' is of uniform length. Otherwise, what do you fill in the array for unused elements?

How do i initialize int[][]?

In C# how do i initialize
int[][] test;
I don't want to use int[,] instead. I am asking specifically how to initialize the above. The obvious = int[1][1] does not work. I tried a few different ways with no luck and [][] is not really google-able unfortunately (unless its possible!?)
It's called jagged arrays if you want to Google it.
Basically you can initialize the first dimension in the traditional way :
int[][] test = new int[23][];
And you manually initialize the others :
for (int i = 0; i < test.Length; ++i)
test[i] = new int[42];
You need a for-loop to initialize an array of array.
int[][] test = new int[N][];
for (int i = 0; i < test.Length; i ++)
test[i] = new int [M];
int[][] scores = new int[5][];
This is called a Jagged Array. So basically you have initialize the "first dimension" first and then each element:
int[][] foo = new int[3][];
foo[0] = new int[2];
...

Categories

Resources