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)
Related
I am taking a class in c# programming and cannot figure out how to do the following. I have spent hours researching and nobody else seems to have the same issues.
The question is:
Write a function named, evenOrOdd, that will accept three parameters. The first parameter is the integer array used in the above function. The second parameter is the string array from step 2 and the third parameter is an integer indicating the size of the two arrays. This function will perform the following tasks:
This function will loop through the first array, checking each value to see if it is even or odd.
For each item in the integer array, the function will then place the appropriate value, “even” or “odd”, in the corresponding position of the string array.
Hint: Using the modulus operator, (also called the modulo), to divide the number by 2 will result in either a remainder of 0 or 1. A remainder of 0 indicates an even number and a remainder of 1 indicates an odd number. The modulus operator for all of the languages in this class is %.
After calling both functions, print the maximum number determined by findMax as well as the array index position of the largest number. Next, the program will loop through the two arrays and print the integer from integer array followed by the corresponding “even” or “odd” value from the string array
I do not understand how to populate the second string array with "even" or "odd".
The two arrays should be something like this:
array1 [1,2,3,4,5,6,7,8,9,10]
then run through a loop to determine if the values are even or odd and then assign the values to the second array so it is something like this:
array2 [odd,even,odd,even,odd,even,odd,even,odd,even]
I am confused how I "link" these two arrays together so that it know index of array 1=index of array 2.
You don't have to "link" the arrays together. You can use a variable which contains the current index and use it for both arrays. Like this:
for (int i = 0; i < array1.Length; i++){
//array1[i]...
//array2[i] = ...
}
This way, you can check if the number at index i in array 1 is even or odd and then modify the index i of array 2 accordingly.
Instead of array1.Length, you can also use the third argument of the method.
It looks like a code challenge. I highly recommend you find your own way to understand and solve this kind of problem and the fundamental concepts behind it as well.
One way to code the EvenOrOdd method:
public void EvenOrOdd(int[] numbers,
string[] natures, int size)
{
for(int i=0; i < size; i++)
if(numbers[i] % 2 == 0)
natures[i] = "even";
else
natures[i] = "odd";
}
One wat to code FindMax Function:
public static (int MaxValue, int MaxIndex) FindMax(int[] numbers)
{
int major = int.MinValue;
int majorIndex = -1;
for(int i=0; i < numbers.Length; i++)
if(numbers[i] > major)
{
major = numbers[i];
majorIndex = i;
}
return (major, majorIndex);
}
Check it in dotnetFiddle
There i try to specify bounds of an array:
public string[] scaleChanged()
{
int j =0;
for(int i=0;i<42;i++)
{
if(MinScale == ItemScale[i]) //MinScale is the min value I want to use to start array
{
ItemsScale[j] = MinScale; //ItemScal is an array of 42 string
for(int h =0; h<42-i; h++)
{
ItemScale[j+1] = ItemScale[i];
j++;
if(ItemScale[j] == MaxScale) //MaxScale is my max value I want to use for stop my array
{
return ItemScale[ ???MinScale to MaxScale];
}
}
}
}
}
So I recover 2 value from a server which allow me to specify bounds of my array.
So I try to define a new array with this two values as bounds.I precise this "two values" are always declared anywhere in my ItemScale array (that is why i use comparaison).
If really depends what you are trying to do here. The bounds of an array are fixed at creation, and in the case of a vector (string[] is a vector), it is always zero-based. If you want an actual array, then you'll need to copy out the sub-range into a second array - just new the array of the correct size, and Array.Copy the element range you want - i.e. Array.Copy(source, startIndex, destination, 0, count);. However, there are ways to represent a range without copying:
if the receiver just needs to iterate the data (rather than access it by index), an IEnumerable<T> - i.e. return source.Skip(firstIndex).Take(count);
Span<T> or ReadOnlySpan<T>, i.e. return new Span<string>(source, firstIndex, count) - a "span" works much like an array, and doesn't require any copying, and is allocation-free; the offset etc is applied appropriately; note that once you have a span, .Slice(...) creates smaller and smaller sub-sections inside that span, again without any copying or allocations
one nice thing here is that you can use the span approach as a simpler way of dealing with creating a new array if you want - once you have a [ReadOnly]Span<T>, you can use .ToArray() to create a new array with those contents
Memory<T> or ReadOnlyMemory<T> is effectively "I can give you a span when you want one" - because you can't store a "span" as a field (it is only legal on the stack), but you can store a "memory"
ArraySegment<T> is an older metaphor for expressing an array with offset and count; it relies on the caller doing everything correctly
I'm trying to do a simple sorting of my own (I know Array.Sort() exists), receiving a user input array and then calling the method sortMyArray() to sort the numbers from smallest to largest. Which does what intended, except for when I try to find the smallest number of an array that contains 0.
As you will see: I'm initialising the variable smallest to the value int.MaxValue at each iteration, but if the array contains a 0, it stays set to to the int.MaxValue.
static int findSmallest(int[] original, int[] sorted, int smallest)
{
for (int i = 0; i < sorted.Length; i++)
{
if (original[i] < smallest & !sorted.Contains(original[i]))
{
smallest = original[i];
}
}
return smallest;
}
static int[] sortMyArray(int[] original)
{
int[] sorted = new int[original.Length];
for (int i = 0; i < sorted.Length; i++)
{
int smallest = int.MaxValue;
smallest = findSmallest(original, sorted, smallest);
sorted[i] = smallest;
}
return sorted;
}
sortMyArray(inputArray);
My question is, how can I make sure 0 is properly handled?
The code behaves as intended for positive and negative integer values, but what is causing the 0 to not work?
Edit: For example, if the inputArray contains {5, -1, 7, 0, 33}, then the method will return it sorted as such: {-1, 5, 7, 33, 2147483647}.
With !sorted.Contains(original[i]) you skip over any value that is already in the array. sorted is initialized to all 0's so it will never set smallest = 0. In your last iteration in sortMyArray, smallest will be equal to int.Max. Note, this will also happen when you have the same element twice. Since you want to implement your own sorting method (and not use Array.Sort), you should look into various sorting algorithms (i.e. Merge Sort, Quick Sort, etc.) as yours won't work as intended.
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);
}
}
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;