What are the differences between using int[][] and int[,]? [duplicate] - c#

This question already has answers here:
Differences between a multidimensional array "[,]" and an array of arrays "[][]" in C#?
(12 answers)
Closed 9 years ago.
Coming from a perl background, I have always defined a 2D array using int[][]. I know you can use int[,] instead so what are the differences?

The difference here is that the first sample, int[][] creates a jagged array, while the second creates a rectangular array (of dimension 2). In a jagged array each "column" can be of a different size. In a true multidimensional array, each "column" (in a dimension) is the same size. For more complete information see the Array section of the C# Programming Guide.

Here's a good comparison
Basically int[][] is a "jagged" array, it looks like this:
[] -> [1, 2, 3]
[] -> [1, 2]
[] -> [1, 2, 3, 4]
While int[,] is a multidimentional array which always has the same width and height:
[1, 2, 3, 4
5, 6, 7, 8
9, 1, 2, 3]
Each have their uses depending on what you're trying to accomplish.

int[][] is an array of arrays or "jagged" array: you can use this when you want different sizes in the second dimension. For example, the first sub array can have 5 elements and the second can have 42.
int[,] is a two dimensional array: The second dimension is the same through out the array. With int[7, 42] the second dimension is 42 for all 7 lines.

int[][] is a jagged array, where int[,] is a two dimensional array.
plainly
var a = int[][]
allows you do have an array like this:
a[0] = new int[2];
a[1] = new int[5];
where as with int[,] you must always have the second portion of the array be the same:
var a = int[2,2];
a[0,0]
a[0,1]
a[1,0]
a[1,1]
you can't have a[2,2];

int[][] is called an array of arrays, it can have arbitrary length for each row.
int[,] is called rectangular array, where all the rows have the same length. it Can be simulated by the first one.

The best way to understand the difference is to look at two ways to create an nxn matrix:
const int n = 8, m = 8;
int[,] matrix1 = new int[n,m];
int[][] matrix2 = new int[n][];
for (int i = 0; i < matrix2.Length; i++) { matrix2[i] = new int[m]; }
matrix1[1,1] = matrix2[2][2];
As you can see the second one is a bit more involved because you need the for-loop to fully create it. It is often called a jagged array because the 2nd order arrays do not need to be all of the same length.

One thing to consider about a jagged array is that you are allocating non-contiguous chunks of memory. This is a good thing if you have a large array of large objects. I've seen SomeThing[n,n] create StackOverflow issues, but SomeThing[n][n] be ok.
Also, if an object gets > 85,000 bytes it goes to the LOH (Large Object Heap).
.NET Collections and the Large Object Heap (LOH)

Here's an excellent article about arrays, covering this topic very well.

you can see int[][] as to (int[])[]
(int[]) is a object

Related

Fastest way to extend array

I am looking for fastest way to extend an array.
No matter if only for length + 1 or length + x it has to be the most fastest way.
Here is an example:
var arr = new int [200];
for(int = 0; i < 200; i++)
arr[i] = i;
And now I want to extend arr for 5 items beginning at index position 20.
var arr2 = new int [] { 999, 999, 999, 999, 999 }
How do I place arr2 inside arr by using most fast way in terms of performance?
The result shall look like this
0,1,2,3,4....20, 999, 999, 999, 999, 999, 21, 22, 23, 24....199
Create a new array which is the size you want, then use the static Array.Copy method to copy the original arrays into the new one.
You can't "extend" an array, you can only create a bigger one and copy the original into it.
Also, consider using List<int> or LinkedList<> instead of an array, unless you require extremely fine-grained control over what is in memory.
It is far easier to use List. But if you have to use arrays, you have to create new array of size 205 and copy values from both source arrays, since array size is constant.
Your best bet is to use something like List<int> rather than an array. But if you must use an array:
int[] arr1 = new int[200];
// initialize array
int[] arr2 = new int[]{999, 999, 999, 999, 999};
int targetPos = 20;
// resizes the array, copying the items
Array.Resize(ref arr1, arr1.Length + arr2.Length);
// move the tail of the array down
Buffer.BlockCopy(arr1, 4*targetPos, arr1, 4*(targetPos+arr2.Length), 4*(arr1.Length - targetPos));
// copy arr2 to the proper position
Buffer.BlockCopy(arr2, 0, 4*arr1.targetPos, 4*arr2.Length);
It might be faster to create a new array and copy the items, like this.
int[] newArray = new int[arr1.Length + arr2.Length];
// copy first part of original array
Buffer.BlockCopy(arr1, 0, newArray, 0, 4*targetPos);
// copy second array
Buffer.BlockCopy(arr2, 0, newArray, 4*targetPos, 4*arr2.Length);
// copy remainder of original array
Buffer.blockCopy(arr1, 4*targetPos, newArray, 4*(targetPos + arr2.Length), 4*(arr1.Length - targetPos));
// and replace the original array
arr1 = newArray;
Which version is faster will depend on where targetPos is. The second version will be faster when targetPos is small. When targetPos is small, the first version has to copy a lot of data twice. The second version never copies more than it has to.
BlockCopy is kind of a pain to work with because it requires byte offsets, which is the reason for all the multiplications by four in the code. You might be better off using Array.Copy in the second version above. That will prevent you having to multiply everything by 4 (and forgetting sometimes).
If you know how long the array will be dimension it to that length,
var ints = new int[someFixedLength];
If you have a vauge idea of the length, use a generic list.
var ints = new List<int>(someVagueLength);
both types implement IList but, the List type handles the redimensioning of the internal array is generically the "most fast" way.
Note: the initial .Count of the List will be 0 but, the internal array will be dimensioned to size you pass to to the constructor.
If you need to copy data between arrays, the quickest way is Buffer.BlockCopy, so from your example
Buffer.BlockCopy(arr2, 0, arr, sizeof(int) * 20, sizeof(int) * 5);
copies all 5 ints from arr2 into indecies 20, 21 ... 24 of arr.
there is no faster way to do this with c# (currently).
An answer showing timing benchmarks is given here: Best way to combine two or more byte arrays in C# . If you consider the "array you insert into " as arrays 1 and 3, and the "array to be inserted" as array 2, then the "concatenate three arrays" example applies directly.
Note the point at the end of the accepted answer: the method that is faster at creating yields an array that is slower to access (which is why I asked if you cared about speed to create, or access speed).
using System.Linq you can do the following to extend an array by adding one new object to it...
int[] intA = new int[] { 1, 2, 3 };
int intB = 4;
intA = intA.Union(new int[] { intB }).ToArray();
...or you can extend an array by adding another array of items to it...
int[] intA = new int[] { 1, 2, 3 };
int[] intB = new int[] { 4, 5, 6 };
intA = intA.Union(intB).ToArray();
...or if you don't care about duplicates...
int[] intA = new int[] { 1, 2, 3 };
int[] intB = new int[] { 4, 5, 6 };
intA = intA.Concat(intB).ToArray();

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();

What is the difference between these two ways of declaring an array? [duplicate]

This question already has answers here:
Differences between a multidimensional array "[,]" and an array of arrays "[][]" in C#?
(12 answers)
Closed 1 year ago.
What is the difference between:
int [][] myArray;
and
int [,] myOtherArray;
The first is a jagged array: an array where each item in the array is another array
int[][] jaggedArray = new int[3][];
jaggedArray[0] = new int[5];
jaggedArray[1] = new int[4];
jaggedArray[2] = new int[2];
The second is a multidimensional array, aka a matrix.
int[,] array = new int[4, 2]; // create a 4 by 2 matrix
myArray is a jagged array, or an array of arrays. Each element of myArray is itself an int[].
myOtherArray is a rectangular (or multidimensional) array - a single object containing all the data directly.
Which you should use really depends on the situation. Sometimes it can be handy to have an array for each "row" of data (with the ability to replace whole rows, and have rows with different lengths), whereas at other times it makes sense to force a uniform layout.
I found the best way to understand it was to see a graphical representation of it =)
int[][] jagged = new int[3][];
jagged[0] = new int[1];
jagged[1] = new int[2];
jagged[2] = new int[4];
will look like this
[0] - [0]
[1] - [0][1]
[2] - [0][1][2][3]
while a two+ dimensional
int[,] twodimensional = new int[3,4]
will look like this
[0,0][0,1][0,2][0,3]
[1,0][1,1][1,2][1,3]
[2,0][2,1][2,2][2,3]
The first is a jagged array, the other multi-dimensional - the difference is that the elements of a jagged array can be of different dimensions and sizes.
Jagged array:
int [][] myArray;
Rectangular array:
int [,] myOtherArray;
Quote Comparing Rectangular and Jagged Arrays :
The structure of rectangular and
jagged arrays is significantly
different.
One-dimensional arrays have specific
instructions in the CIL that allow
them to be optimized for performance.
Rectangular arrays do not have these
instructions, and are not optimized to
the same level. Because of this, it
can sometimes be more efficient to use
jagged arrays of one-dimensional
arrays—which can be optimized—than
rectangular arrays, which cannot. On
the other hand, the programming
complexity can be less for a
rectangular array because it can be
treated as a single unit, rather than
an array of arrays.
This has to be a duplicate. One is a jagged array, one is a two-dimensional array. You should be able to take it from there.
Both statements declare uninitialized multi-dimensional arrays of ints. The first is a jagged array and the second is 2-dimensional.
You can initialize the 2-dimensional array at the same time as you declare it as follows:
int[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
OR,
int[,] array = new int[4, 2];
Refer to the official documentation:

LINQ: transform an array [,] into array[]

I know this is kind of a dumb question, but does anyone have an elegant (or non-elegant) LINQ approach to transform a 2D array (object[,]) into a 1D array (object[]) comprised of the first dimension of the 2D array?
Example:
// I'd like to have the following array
object[,] dim2 = {{1,1},{2,2},{3,3}};
// converted into this kind of an array... :)
object[] dim1 = { 1, 2, 3 };
You claim that you want a 1D array (object[]) comprised of the first dimension of the 2D array, so I assume you are trying to select a subset of the original 2D array.
int[,] foo = new int[2, 3]
{
{1,2,3},
{4,5,6}
};
int[] first = Enumerable.Range(0, foo.GetLength(0))
.Select(i => foo[i, 0])
.ToArray();
// first == {1, 4}
#Elisha had posted an answer (didn't compile initially) also, which I was investigating this afternoon. I don't know why he deleted his answer, but I carried on with his code example until everything got worked out, and it also gives me what I need:
object[,] dim2 =
{{"ADP", "Australia"}, {"CDN", "Canada"}, {"USD", "United States"}};
object[] dim1 = dim2.Cast<object>().ToArray();
// dim1 = {"ADP", "CDN", "USD"}
This code compiles and returns the expected results. I glad about the .Cast(), and that I only needed the first dimension, not the second.
In general, for a collection of collections (instead of an array of arrays), you can do:
mainCollection.Select(subCollection => subCollection.First());

Categories

Resources