Related
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.
Consider the following method of shuffling, given an array of objects a
Take the first element from a and place it into b. Consider the index of this element inside b to be x.
Place the second element from a and place it in front of b[x], so that it is now in position b[x-1]
Place the third element from a and place it behind b[x], so that it is now in position b[x+1]
Place the fourth element from a and place it in front of b[x - 1], so that it is now in position b[x-2]
Place the firth element from a and place it behind b[x+1] so that it is now in position b[x+2]
Repeat this process until b has all of the elements from a in it in this new shuffled order.
I wrote some code which does this, shown below. It will continuously shuffle the array in the above process until the shuffled array matches the original array, and then return the number of shuffles.
public class BadShuffler
{
public BadShuffler(object[] _arrayToShuffle)
{
originalArray = _arrayToShuffle;
Arrays = new List<object[]>
{
originalArray
};
}
private object[] originalArray;
private int count;
public List<object[]> Arrays { get; set; }
public int Shuffle(object[] array = null)
{
if (array == null)
array = originalArray;
count++;
object[] newArray = new object[array.Length];
bool insertAtEnd = false;
int midpoint = newArray.Length / 2;
newArray[midpoint] = array[0];
int newArrayInteger = 1;
int originalArrayInteger = 1;
while (newArray.Any(x => x == null))
{
if (insertAtEnd)
{
newArray[midpoint + newArrayInteger] = array[originalArrayInteger];
newArrayInteger++;
}
else
{
newArray[midpoint - newArrayInteger] = array[originalArrayInteger];
}
originalArrayInteger++;
insertAtEnd = !insertAtEnd;
}
Arrays.Add(newArray);
return (newArray.All(x => x == originalArray[Array.IndexOf(newArray, x)])) ? count : Shuffle(newArray);
}
}
While not being the prettiest thing in the world, it does the job. Example shown below:
Shuffled 6 times.
1, 2, 3, 4, 5, 6
6, 4, 2, 1, 3, 5
5, 1, 4, 6, 2, 3
3, 6, 1, 5, 4, 2
2, 5, 6, 3, 1, 4
4, 3, 5, 2, 6, 1
1, 2, 3, 4, 5, 6
However, if I give it an array of [1, 2, 3, 3, 4, 5, 6] it ends up throwing a StackOverflowException. When debugging, however, I have found that it does actually get to a point where the new shuffled array matches the original array, as shown below.
This then goes on to call Shuffle(newArray) again, even though all values in the array match each other.
What is causing this? Why does the Linq query newArray.All(x => x == originalArray[Array.IndexOf(newArray, x)]) return false?
Here is a DotNetFiddle link, which includes the code I used to print out the result(s)
You are comparing objects. objects are compared using referential equality with ==, not value equality. Your example uses numbers, but those numbers are boxed to an object implicitly due to the way your code is laid out.
To avoid this, you should use the .Equals() function (when comparing Objects).
newArray.All(x => x.Equals(originalArray[Array.IndexOf(newArray, x)]))
You should also use generics in your class instead of littering object[] everywhere to ensure type safety - unless one of your aims with this shuffler is to allow the shuffler to shuffle arrays of mixed types (which seems doubtful since it would be hard to extract any useful information out of that).
Note that this behaviour is exhibited whenever you are comparing reference types; one way to only allow value types to be passed to your structure (i.e, only primitive values that can be compared by value equality rather than referential equality) is to use the struct generic constraint. As an example:
class BadShuffler<T> where T : struct
{
public bool Shuffle(T[] array)
{
...
return newArray.All(x => {
var other = originalArray[Array.IndexOf(originalArray, x)];
return x == other;
});
}
}
This would work as you expect.
SequenceEqual as mentioned in the comments is also a good idea, as your .All() call will say that [1, 2, 3] is equal to [1, 2, 3, 4], but [1, 2, 3, 4] will not be equal to [1, 2, 3] - both of these scenarios are incorrect and more importantly not commutative[1], which equality operations should be.
Just make sure you implement your own EqualityComparer if you go beyond using object[].
That said, I think you want to use a combination of both approaches and use SequenceEqual with my approach, unless you need to shuffle objects (I.e, a Deck of Cards) rather than numbers?
As a side note, I would generally recommend returning a new, shuffled T[] rather than modifying the original one in-place.
[1]: Commutative means that an operation done one way can be done in reverse and you get the same result. Addition, for example, is commutative: you can sum 1, 2 and 3 together in any order but the outcome will always be 6.
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
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)
I just came across the ArraySegment<byte> type while subclassing the MessageEncoder class.
I now understand that it's a segment of a given array, takes an offset, is not enumerable, and does not have an indexer, but I still fail to understand its usage. Can someone please explain with an example?
ArraySegment<T> has become a lot more useful in .NET 4.5+ and .NET Core as it now implements:
IList<T>
ICollection<T>
IEnumerable<T>
IEnumerable
IReadOnlyList<T>
IReadOnlyCollection<T>
as opposed to the .NET 4 version which implemented no interfaces whatsoever.
The class is now able to take part in the wonderful world of LINQ so we can do the usual LINQ things like query the contents, reverse the contents without affecting the original array, get the first item, and so on:
var array = new byte[] { 5, 8, 9, 20, 70, 44, 2, 4 };
array.Dump();
var segment = new ArraySegment<byte>(array, 2, 3);
segment.Dump(); // output: 9, 20, 70
segment.Reverse().Dump(); // output 70, 20, 9
segment.Any(s => s == 99).Dump(); // output false
segment.First().Dump(); // output 9
array.Dump(); // no change
It is a puny little soldier struct that does nothing but keep a reference to an array and stores an index range. A little dangerous, beware that it does not make a copy of the array data and does not in any way make the array immutable or express the need for immutability. The more typical programming pattern is to just keep or pass the array and a length variable or parameter, like it is done in the .NET BeginRead() methods, String.SubString(), Encoding.GetString(), etc, etc.
It does not get much use inside the .NET Framework, except for what seems like one particular Microsoft programmer that worked on web sockets and WCF liking it. Which is probably the proper guidance, if you like it then use it. It did do a peek-a-boo in .NET 4.6, the added MemoryStream.TryGetBuffer() method uses it. Preferred over having two out arguments I assume.
In general, the more universal notion of slices is high on the wishlist of principal .NET engineers like Mads Torgersen and Stephen Toub. The latter kicked off the array[:] syntax proposal a while ago, you can see what they've been thinking about in this Roslyn page. I'd assume that getting CLR support is what this ultimately hinges on. This is actively being thought about for C# version 7 afaik, keep your eye on System.Slices.
Update: dead link, this shipped in version 7.2 as Span.
Update2: more support in C# version 8.0 with Range and Index types and a Slice() method.
Buffer partioning for IO classes - Use the same buffer for simultaneous
read and write operations and have a
single structure you can pass around
the describes your entire operation.
Set Functions - Mathematically speaking you can represent any
contiguous subsets using this new
structure. That basically means you
can create partitions of the array,
but you can't represent say all odds
and all evens. Note that the phone
teaser proposed by The1 could have
been elegantly solved using
ArraySegment partitioning and a tree
structure. The final numbers could
have been written out by traversing
the tree depth first. This would have
been an ideal scenario in terms of
memory and speed I believe.
Multithreading - You can now spawn multiple threads to operate over the
same data source while using segmented
arrays as the control gate. Loops
that use discrete calculations can now
be farmed out quite easily, something
that the latest C++ compilers are
starting to do as a code optimization
step.
UI Segmentation - Constrain your UI displays using segmented
structures. You can now store
structures representing pages of data
that can quickly be applied to the
display functions. Single contiguous
arrays can be used in order to display
discrete views, or even hierarchical
structures such as the nodes in a
TreeView by segmenting a linear data
store into node collection segments.
In this example, we look at how you can use the original array, the Offset and Count properties, and also how you can loop through the elements specified in the ArraySegment.
using System;
class Program
{
static void Main()
{
// Create an ArraySegment from this array.
int[] array = { 10, 20, 30 };
ArraySegment<int> segment = new ArraySegment<int>(array, 1, 2);
// Write the array.
Console.WriteLine("-- Array --");
int[] original = segment.Array;
foreach (int value in original)
{
Console.WriteLine(value);
}
// Write the offset.
Console.WriteLine("-- Offset --");
Console.WriteLine(segment.Offset);
// Write the count.
Console.WriteLine("-- Count --");
Console.WriteLine(segment.Count);
// Write the elements in the range specified in the ArraySegment.
Console.WriteLine("-- Range --");
for (int i = segment.Offset; i < segment.Count+segment.Offset; i++)
{
Console.WriteLine(segment.Array[i]);
}
}
}
ArraySegment Structure - what were they thinking?
What's about a wrapper class? Just to avoid copy data to temporal buffers.
public class SubArray<T> {
private ArraySegment<T> segment;
public SubArray(T[] array, int offset, int count) {
segment = new ArraySegment<T>(array, offset, count);
}
public int Count {
get { return segment.Count; }
}
public T this[int index] {
get {
return segment.Array[segment.Offset + index];
}
}
public T[] ToArray() {
T[] temp = new T[segment.Count];
Array.Copy(segment.Array, segment.Offset, temp, 0, segment.Count);
return temp;
}
public IEnumerator<T> GetEnumerator() {
for (int i = segment.Offset; i < segment.Offset + segment.Count; i++) {
yield return segment.Array[i];
}
}
} //end of the class
Example:
byte[] pp = new byte[] { 1, 2, 3, 4 };
SubArray<byte> sa = new SubArray<byte>(pp, 2, 2);
Console.WriteLine(sa[0]);
Console.WriteLine(sa[1]);
//Console.WriteLine(b[2]); exception
Console.WriteLine();
foreach (byte b in sa) {
Console.WriteLine(b);
}
Ouput:
3
4
3
4
The ArraySegment is MUCH more useful than you might think. Try running the following unit test and prepare to be amazed!
[TestMethod]
public void ArraySegmentMagic()
{
var arr = new[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
var arrSegs = new ArraySegment<int>[3];
arrSegs[0] = new ArraySegment<int>(arr, 0, 3);
arrSegs[1] = new ArraySegment<int>(arr, 3, 3);
arrSegs[2] = new ArraySegment<int>(arr, 6, 3);
for (var i = 0; i < 3; i++)
{
var seg = arrSegs[i] as IList<int>;
Console.Write(seg.GetType().Name.Substring(0, 12) + i);
Console.Write(" {");
for (var j = 0; j < seg.Count; j++)
{
Console.Write("{0},", seg[j]);
}
Console.WriteLine("}");
}
}
You see, all you have to do is cast an ArraySegment to IList and it will do all of the things you probably expected it to do in the first place. Notice that the type is still ArraySegment, even though it is behaving like a normal list.
OUTPUT:
ArraySegment0 {0,1,2,}
ArraySegment1 {3,4,5,}
ArraySegment2 {6,7,8,}
In simple words: it keeps reference to an array, allowing you to have multiple references to a single array variable, each one with a different range.
In fact it helps you to use and pass sections of an array in a more structured way, instead of having multiple variables, for holding start index and length. Also it provides collection interfaces to work more easily with array sections.
For example the following two code examples do the same thing, one with ArraySegment and one without:
byte[] arr1 = new byte[] { 1, 2, 3, 4, 5, 6 };
ArraySegment<byte> seg1 = new ArraySegment<byte>(arr1, 2, 2);
MessageBox.Show((seg1 as IList<byte>)[0].ToString());
and,
byte[] arr1 = new byte[] { 1, 2, 3, 4, 5, 6 };
int offset = 2;
int length = 2;
byte[] arr2 = arr1;
MessageBox.Show(arr2[offset + 0].ToString());
Obviously first code snippet is more preferred, specially when you want to pass array segments to a function.