How to initialize multi-dimensional array with different default value - c#

I am trying to initialize 2-dimensional array of integer values with -1. When I create a new array, it is automatically filled with 0.
I know I can do it with 2 for cycles, but I imagine there should be some way of doing this while the array is being build (so I don't have to go through it two times), so that instead of 0, provided value would be inserted. Is it possible?
If not during the initial building of the array, is there some other time or code saving way, or am I stuck with 2 for cycles?

Try something like this: int[,] array2D = new int[,] { { -1 }, { -1 }, { -1 }, { -1} };
or with dimension int[,] array2D = new int[4,2] { { -1,-1 }, { -1,-1 }, { -1,-1 }, {-1,-1} };

With a multidimensional array, the loops are most likely the best approach, unless the array is small enough to initialize directly in code.
If you're using a jagged array, you could initialize the first sub-array, then use Array.Copy to copy these values into each other sub-array. This will still require one iteration through the first sub array, and one loop through N-1 outer arrays, but the copy operation will be faster than the loops.

In Python, this kind of 2D array initialization is wrong:
mat = [[0] * 5] * 5 # wrong
mat = [[0] * 5] for _ in range(5)] # correct
because you are copying the reference of the inner array multiple times, and changing one of them will eventually change all.
mat[0][0] = 1
print(mat)
# 1 0 0 0 0
# 1 0 0 0 0
# 1 0 0 0 0
# 1 0 0 0 0
# 1 0 0 0 0
In C#, we have the similar issue.
var mat = Enumerable.Repeat(Enumerable.Repeat(0, 5).ToArray(), 5).ToArray();
Since array is a reference type, the outside Repeat() are actually copying the reference of the inner array.
Then if you do have the need to create and initialize multidimensional arrays without using for loops, then maybe a custom helper class will help:
static class HelperFunctions
{
public static T[][] Repeat<T>(this T[] arr, int count)
{
var res = new T[count][];
for (int i = 0; i < count; i++)
{
//arr.CopyTo(res[i], 0);
res[i] = (T[])arr.Clone();
}
return res;
}
}
Then if you want to use it:
using static HelperFunctions;
var mat = Enumerable.Repeat(0, 5).ToArray().Repeat(5);
This will do.

Related

C# reset an array to its initialized values?

Lets say I have an array of employee wages in the order of average, max, and min:
int[] wages = {0, 0, Int32.MaxValue};
The above code is initalized so that as Im finding the max I can do a comparison to 0 and anything above the existing value will beat it and replace it. So 0 works fine here. Looking at the min, if I were to set that to 0 I'd have a problem. Comparing wages (all greater than 0) and replacing the minimum with the lowest wage will be impossible because none of the wages would be below the 0 value. So Instead I've used Int32.MaxValue because It's guaranteed every wage will be below this value.
This is just one example but there are others where it would be convenient to reset and array back to its initialized contents. Is there syntax for this in c#?
EDIT: #Shannon Holsinger found an answer with:
wages = new int[] {0, 0, Int32.MaxValue};
Short answer is that there's not a built-in way of doing this. The framework doesn't automatically keep track of your array's initial state for you, just its current state, so it has no way of knowing how to re-initialize it to its original state. You could do it manually though. The exact approach to this depends on what your array was initialized to in the first place:
// Array will obviously contain {1, 2, 3}
int[] someRandomArray = { 1, 2, 3 };
// Won't compile
someRandomArray = { 1, 2, 3 };
// We can build a completely new array with the initial values
someRandomArray = new int[] { 1, 2, 3 };
// We could also write a generic extension method to restore everything to its default value
someRandomArray.ResetArray();
// Will be an array of length 3 where all values are 0 (the default value for the int type)
someRandomArray = new int[3];
The ResetArray extension method is below:
// The <T> is to make T a generic type
public static void ResetArray<T>(this T[] array)
{
for (int i = 0; i < array.Length; i++)
{
// default(T) will return the default value for whatever type T is
// For example, if T is an int, default(T) would return 0
array[i] = default(T);
}
}

Syntax to create a double[,] in C#

This seems extremely simple, yet I can't seem to find applicable documentation anywhere. In C#, how do you create a 'double[,]'? Specifically, the data I'm trying to represent is something like this:
[0,0] = 0
[0,1] = 1
[1,0] = 1
[1,1] = 2
I have tried [[0,1],[1,2]] and the equivalent with {{}{}} and {[][]} and various other things, but cannot seem to figure out the syntax. It seems that a simple [0,1] alone is a 'double[,]' but I would like to find a way to represent the above data (more than just 2 numbers).
What am I missing? If anyone can point me to some simple documentation, that would be great.
See Array initializers:
For a multi-dimensional array, the array initializer must have as many levels of nesting as there are dimensions in the array. The outermost nesting level corresponds to the leftmost dimension and the innermost nesting level corresponds to the rightmost dimension. The length of each dimension of the array is determined by the number of elements at the corresponding nesting level in the array initializer. For each nested array initializer, the number of elements must be the same as the other array initializers at the same level.
In our case:
double[,] a = { { 0, 1 }, { 1, 2 } };
A multi-dimensional double array:
Double[,] newdouble = new Double[2,2];
or
Double[,] newdouble = { { 0, 0 }, { 1, 1 } };
In order to create a two dimensional array that you can assign to, you are going to need to first allocate the correct size. In this case, you have 2 rows and 2 columns, so that will be a [2,2].
double[,] twod = new double[2,2];
Next you simply assign to it like this
twod[0,0] = 0;
twod[0,1] = 1;
twod[1,0] = 1;
twod[1,1] = 2;
And then work with it however you wish.
There is three ways to initialized your array:
double[,] twoDemn = { { 0 , 1 }, { 1 , 2 } };
or:
double[,] twoDemn = new double[,] { { 0 , 1 }, { 1 , 2 } };
or:
double[,] twoDemn = new double[2,2];
twoDemn[0,0] = 0;
twoDemn[0,1] = 1;
twoDemn[1,0] = 1;
twoDemn[1,1] = 2;

How should I properly compare my array index value against array length

Say I have an array that has 5 values int[] gear = new int[] {5,4,3,2,1}; and I also have a variable that I use to get the value I want int currentGear = 0; Now I would like to step through the array under a certain condition with this code:
if(rpm > shiftRPM && currentGear < gear.Length)
currentGear++;
Console.WriteLine( gear[cuurentGear] );
However, using that code I am able to go past the array length because gear.Length is 5, but array's are zero indexed(i.e. the max number I can have is 4).
So my solution is to just add 1 to currentGear in the if statement, but this for loops works as expected:
for(int i=0; i<gear.Length;i++;)
Console.Write(gear[i]);
And outputs: 5 4 3 2 1 with no errors.
Also, if I Console.Write(gear.Length); it outputs 5, so clearly my error is with my if statement allowing my index to pass gear.Length since 4 < 5 and 5 is out of range.
Is there a better way to increment my array index variable than doing this:
if(rpm > shiftRPM && (currentGear+1) < gear.Length)
currentGear++;
or is that the best way to handle this situation?
Your solution is basically the best way. The maximum value of an index is in fact Length-1, not Length, so when you only check that currentGear is less than Length, you are not really guarding against it getting too large.
why not initialize currentGear as:
var currentGear = -1;

How can we find items count in the C# integer array?

I need to find items count in the C# array which type is integer.
What I mean is;
int[] intArray=new int[10]
int[0]=34
int[1]=65
int[2]=98
Items count for intArray is 3.
I found the code for strArray below but It doesn't work for int arrays.
string[] strArray = new string[50];
...
int result = strArray.Count(s => s != null);
Well, first you have to decide what an invalid value would be. Is it 0? If so, you could do this:
int result = intArray.Count(i => i != 0);
Note that this only works because, by default, elements of an int array are initialized to zero. You'd have to fill the array with a different, invalid value beforehand if 0 ends up being valid in your situation.
Another way would be to use a nullable type:
int?[] intArray = new int?[10];
intArray[0] = 34;
intArray[1] = 65;
intArray[2] = 98;
int result = intArray.Count(i => i.HasValue);
While itsme86 provided you a good answer to your actual question, I suspect you may be better off reconsidering how you write this entirely.
If this is your goal, I would recommend thinking about this differently. Instead of allocating a fixed size array, and only assigning specific values to it, you might want to consider using a List<int>:
List<int> intList = new List<int>();
intList.Add(34);
intList.Add(65);
intList.Add(98);
The number of items will always be intList.Count, and you can add as many items as you wish this way, without worry about the "allocated size", since the list will automatically grow as needed. It also won't provide you bad results if you add 0 to the list as an actual value, where counting non-zero elements will not count a zero if it's a valid value.
Note that you can also access the items by index, just like you do with an array:
int secondValue = intList[1]; // Access like you do with arrays
int[] intArray=new int[3] // Edit: Changed this to 3 to make my answer work. :)
int[0]=34
int[1]=65
int[2]=98
int count = intArray.Length; // <-- Is this what you're after?
Edit:
Ahem. As was so humbly pointed out to me, Length will return the total number of elements in the array, which in your example would have been 10. If you are looking for the number of non-zero elements in the array, you should do as suggested in some of the other answers.
When you initialize an integer array without specifying any values, C# assigns a value of zero to every element. So if zero isn't a valid value for your array, you could always test for that.
Alternatively, you could initialize the elements of your array to some value that is invalid in your context (ie if negative numbers aren't valid, initialize to -1), and then loop through the array counting the valid elements.
If the array is guaranteed to only be accessed in sequence, you can beat the full iterative IEnumerable Count (for larger arrays) with a little divide and conquer, e.g.
static int DivideCount(int[] arr, int idx, int bottom, int top)
{
if (idx <= 0)
return 0;
else if (idx >= arr.Length - 1)
return arr.Length;
else if (arr[idx] == 0 && arr[idx - 1] != 0)
return idx;
else if (arr[idx] == 0 && arr[idx - 1] == 0)
return DivideCount(arr, bottom + ((idx - bottom) / 2), bottom, idx);
else if (arr[idx] != 0 && arr[idx - 1] != 0)
return DivideCount(arr, top - ((top - idx) / 2), idx, top);
else
return -1; // hello compiler
}
int[] intArray = new int[10];
intArray[0] = 35;
intArray[1] = 65;
intArray[2] = 98;
var count = DivideCount(intArray, intArray.Length / 2, 0, intArray.Length);
None of the previous solutions are optimal if someone other than you initialized the array (i.e. you don't have the option of initializing the array values to invalid values -- null, -1, etc.).
Suppose you have an array:
var arr = new[] {0, 10, 18, 0, 20, 0, 0, 0, 0, 0, 0, 0};
If you simply count the number of zero entries:
int result = arr.Count(i => i != 0);
Count() returns 3, when in reality 5 entries have been initialized. An example would be an array of raw bytes that were read out of an audio file into a buffer, and you want to know the index of the last element that was read.
An alternative that isn't perfect but could do what you're looking for is to look for the last non-zero entry, as described here: Linq - Get the Index of the Last Non-Zero Number of Array

Difference between array.GetLength(0) and array.GetUpperBound(0)

What is the difference between these two methods and when would you use one instead of the other?
int[,] array = new int[4,3];
int length0 = array.GetLength(0);
int upperbound0 = array.GetUpperBound(0);
MSDN says that GetLength return the number of elements where as GetUpperBound determine the max index, but how could this be different since arrays are initialized with elements for each index?
Take a look at this (rarely used) method. From Docs:
public static Array CreateInstance(Type elementType, int[] lengths, int[] lowerBounds)
Creates a multidimensional Array of the specified Type and dimension lengths, with the specified lower bounds.
With it, you can create an array with indices from -5 ... +5. If you ever use this kind of array, then GetUpperBound() suddenly becomes a lot more useful than GetLength()-1. There also exists a GetLowerBound().
But the C# support for this kind of arrays is low, you cannot use []. You would only need those methods in combination with the Array.GetValue() and SetValue() methods.
Array.Length returns the length of the array (number of elements) you need
to subtract 1 from it to get the UpperBound.
Array.GetUpperBound(0) returns the upper bound of the array, you can use it
as is.
GetUpperBound returns the highest index in the array, the GetLength returns the number of elements of the array.
i.e. GetUpperBound = GetLength - 1
Generally, array.GetUpperBound(0) = array.Length - 1, but since we can create arrays that have a Nonzero lower bound, that is not always true.
I realise this is an old question but I think it's worth emphasising that GetUpperBound returns the upper boundary of the specified dimension. This is important for a multidimensional array as in that case the two functions are not equivalent.
// Given a simple two dimensional array
private static readonly int[,] USHolidays =
{
{ 1, 1 },
{ 7, 4 },
{ 12, 24 },
{ 12, 25 }
};
The Length property will output 8 as there are 8 elements in the array.
Console.WriteLine(USHolidays.Length);
However, the GetUpperBound() function will output 3 as the upper boundary of the first dimension is 3. In other words I can loop over array indexes 0, 1, 2 and 3.
Console.WriteLine(USHolidays.GetUpperBound(0));
for (var i = 0; i <= USHolidays.GetUpperBound(0); i++)
{
Console.WriteLine("{0}, {1}", USHolidays[i, 0], USHolidays[i, 1]);
}
if lower bound of your array is 0 then you can use either of them without any confusion but i would recommend array.length-1 as it is widely used. however, if the lower bound of your array is less than 0 then you should use array.GetUpperBound(0) because in this case array.length-1 != array.getUpperBound(0)

Categories