Issue with dynamically creating jagged array in C# - c#

I am trying to store each iteration of an array as it is being sorted through. For some reason the jagged array I return just becomes an array of the final sorted array. My code is below I cannot figure out why any help would be really appreciated. Thanks.
namespace SortingUI.Utils
{
public class Sorting
{
public static int[][] SortInt(int[] originalArray)
{
int length = originalArray.Length;
int tempVal, smallest;
int[][] iterations = new int[length-1][];
for (int i = 0; i < length - 1; i++)
{
smallest = i;
for (int j = i + 1; j < length; j++)
{
if (originalArray[j] < originalArray[smallest])
{
smallest = j;
}
}
tempVal = originalArray[smallest];
originalArray[smallest] = originalArray[i];
originalArray[i] = tempVal;
iterations[i] = originalArray;
}
return iterations;
}
}
}

If i understand your problem, the reason you are getting the same values (and not a snapshot) is because you are storing a reference to the array, and not a copy of the values themselves.
Arrays are reference types, so when you assign them to another variable you are only copying reference and not the contents. If you change the contents, all the references will reflect that
You can make use of Array.Copy to copy the values at the point in time from the originalArray
...
var tempVal = originalArray[smallest];
originalArray[smallest] = originalArray[i];
originalArray[i] = tempVal;
// Create some new memory
iterations[i] = new int[originalArray.Length];
// Copy the contents
Array.Copy(originalArray, iterations[i], originalArray.Length);
Note this is totally untested and i have no idea if the rest of your code is working as intended
Additional Resources
Array.Copy Method
Copies a range of elements in one Array to another Array and performs
type casting and boxing as required.
Arrays (C# Programming Guide)
Array types are reference types derived from the abstract base type Array. Since this type implements IEnumerable and IEnumerable,
you can use foreach iteration on all arrays in C#.

Related

Unable to cast object of type 'System.Object[,]' to type 'System.Object[]'

I have a dll which gives me as an output an Object[,]
{Name = "Object[,]" FullName = "System.Object[,]"}
I am trying to convert it to Object[] to be able to read it properly, as it is a two columns object.
I have tried to cast it Object[] values = (Object[])data;, but I obtained the error from the tittle:
Unable to cast object of type 'System.Object[,]' to type 'System.Object[]'.
Is there any easy way to perform this operation? I would like to make a dictionary out of it.
Thanks in advance
Rather than using it as an Object[] (which it isn't), use the System.Array API:
var dictionary = new Dictionary<string, string>(); // For example
Array array = (Array) data;
for (int i = 0; i < array.GetLength(0); i++)
{
string key = (string) array.GetValue(i, 0);
string value = (string) array.GetValue(i, 1);
dictionary[key] = value;
}
You can only cast an instance of any type to another one if it implements both types. However object[,] does not derive from object[] so you can´t cast it to that type. At least you should provide which dimension (/column) of the array you want to handle further.
However it is unlcear why you need this. If you´re only interested on the colums instead of the rows then you might simply call myArr[i, 0] or whatever column you´re interested in within a loop on the first dimension of the array.
If you want to iterate your multidimensional array you may either flatten it:
foreach(var on in myArray)
Console.WriteLine(o);
Which will simply loop all the elements without considering its position in the array or
for(int i = 0; i < myArray.GetLength(myColumnIndex); i++)
Console.WriteLine(myArray[i, myColumnIndex]);
Whereby you get only those elements within the given column.
Well of course you cannot cast a multidimensional array to an single dimension array. It is illegal. Check Casting
But as a solution to your problem could be the following logic
object[,] multiDimensionalArray = new object[,]
{
{1,2}, //first pair
{3,4}, //second pair
{5,6} //third pair
};
Dictionary<object, object> dict = new Dictionary<object, object>();
//total number of elements //number of dimensions
int pairs = multiDimensionalArray.Length / multiDimensionalArray.Rank;
//or you can use i < multiDimensionalArray.GetLength(0);
for(int i = 0; i < pairs; i++)
{
dict.Add(multiDimensionalArray[i, 0], multiDimensionalArray[i, 1]);
}

How to clone multidimensional array without reference correctly?

I have 3-dimensional array in my programm. I want to debug values in it and I put this array into another array, in which I want to find difference.
I tried this:
Weights weights = new Weights(); // init inside
List<Weights> weightsDebug = new List<Weigts>();
weightsDebug.Add(weights); // I'd put first weigths into the list
for(int i = 0; i < 100; i++) {
// do some bad things with weights;
weightsDebug.Add(weights);
}
After that, I'd got same values in weights in all 99 elements of weigthsDebug. I'd tried to debug and I'd realised, that weigts array is being changed. I understood that problem is in the reference (copy by link, not by value) – all pushed to weightsDebug array elements are linked with weights in main loop.
I'd googled a bit and found some ways how to copy 1-dimensional array. I'tried next:
I added Clone method to my Weights class:
double[][][] values;
public Weights Clone() {
Weights clone = new Weights();
clone.values = (double[][][]) this.values.Clone();
return clone;
}
public Weights()
{
Console.WriteLine("Constructor WITHOUT arguments fired");
}
Now I am doing so when copy weights:
Weights weights = new Weights(); // init inside
List<Weights> weightsDebug = new List<Weigts>();
weightsDebug.Add(weights); // I'd put first weigths into the list
for(int i = 0; i < 100; i++) {
// do some bad things with weights;
Weights weightsClone = weights.Clone();
weightsDebug.Add(weightsClone);
}
And I am still getting last changed value in whole debug array. How I can correct it?
What you really are looking for here is deep cloning rather than the current shallow cloning that you are implementing.
A long time ago, we realized that by making the classes Serializable, we could use the .Net serialization classes to quickly, easily, and correctly make deep clones of any object.
Here is a method that we use for this deep cloning (there is also a SilverLight variation that uses DataContractSerializer):
/// <summary>
/// This method clones all of the items and serializable properties of the current collection by
/// serializing the current object to memory, then deserializing it as a new object. This will
/// ensure that all references are cleaned up.
/// </summary>
/// <returns></returns>
/// <remarks></remarks>
public T CreateSerializedCopy<T>(T oRecordToCopy)
{
// Exceptions are handled by the caller
if (oRecordToCopy == null)
{
return default(T);
}
if (!oRecordToCopy.GetType().IsSerializable)
{
throw new ArgumentException(oRecordToCopy.GetType().ToString() + " is not serializable");
}
var oFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
using (var oStream = new MemoryStream())
{
oFormatter.Serialize(oStream, oRecordToCopy);
oStream.Position = 0;
return (T)oFormatter.Deserialize(oStream);
}
}
To use this, first ensure the Weights class is tagged with the Serializable attribute:
[Serializable]
public class Weights
Then you can clone as needed:
var weights = new List<Weights>();
weights.Add(new Weights());
var debugWeights = CreateSerializedCopy<List<Weights>>(weights);
if (debugWeights[0] == weights[0])
{
System.Diagnostics.Debug.WriteLine("Did not serialize correctly");
}
The problem here is that you don't have a true multi-dimensional array, where there's just a single object. You have a "jagged" multi-dimensional array, where the object is actually an array of arrays of arrays. This means that to clone the object, you need to do more work:
clone.values = new double[values.Length][][];
for (int i = 0; i < values.Length; i++)
{
clone.values[i] = new double[values[i].Length][];
for (int j = 0; j < values[i].Length; j++)
{
clone.values[i][j] = (double[])values[i][j].Clone();
}
}

NullReferenceException on trying to use my first user-defined type

What I'm trying to do is define my own type that contains 2 ints to use in a 2-dimensional array. The application for this is using the array indexes as x,y coordinates for objects in 2-d space to be displayed. So object with data stored at array[13,5] would be displayed at x=13,y=5, and the properties of that object could be retrieved with array[13,5].property1, for example. The type I've defined is extremely simple:
chunkBlocks.cs:
public class chunkBlocks {
public int blockType;
public int isLoaded;
}
then, I initialize the array:
chunkBlocks[,] _bData = new chunkBlocks[17, 17];
This all compiles/runs without error. The NRE is thrown when I try to assign a value to one of the properties of the type. For debugging, I have the code written as:
_bData[i, n].blockType = 5;
and the NRE is thrown specifically on the .blockType portion. I've tried changing the type to initialize with 0 values for both ints to no avail:
public class chunkBlocks {
public int blockType = 0;
public int isLoaded = 0;
}
I've Googled around and searched SO, and I've not been able to turn up anything. I'm sure it's a relatively simple matter, but I'm not experienced enough to be able to pinpoint it.
Thanks!
You need to initialize every instance of the array:
_bData[i, n] = new chunkBlocks();
Now assign the value to it:
_bData[i, n].blockType = 5;
You will have to initialize every instance, you just have declared them in the array.
I think you should do this:
for(int i = 0;i<17;i++)
{
for (int j = 0; j < 17; j++)
{
_bData[i, j] = new chunkBlocks ();
}
}

Instantiate an array of objects, in simpliest way?

Given a class:
class clsPerson { public int x, y; }
Is there some way to create an array of these classes with each element initialized to a (default) constructed instance, without doing it manually in a for loop like:
clsPerson[] objArr = new clsPerson[1000];
for (int i = 0; i < 1000; ++i)
objArr[i] = new clsPerson();
Can I shorten the declaration and instantiation of an array of N objects?
The constructor must be run for every item in the array in this scenario. Whether or not you use a loop, collection initializers or a helper method every element in the array must be visited.
If you're just looking for a handy syntax though you could use the following
public static T[] CreateArray<T>(int count) where T : new() {
var array = new T[count];
for (var i = 0; i < count; i++) {
array[i] = new T();
}
return array;
}
clsPerson[] objArary = CreateArray<clsPerson>(1000);
You must invoke the constructor for each item. There is no way to allocate an array and invoke your class constructors on the items without constructing each item.
You could shorten it (a tiny bit) from a loop using:
clsPerson[] objArr = Enumerable.Range(0, 1000).Select(i => new clsPerson()).ToArray();
Personally, I'd still allocate the array and loop through it (and/or move it into a helper routine), though, as it's very clear and still fairly simple:
clsPerson[] objArr = new clsPerson[1000];
for (int i=0;i<1000;++i)
clsPerson[i] = new clsPerson();
If it would make sense to do so, you could change class clsPerson to struct Person. structs always have a default value.

C#: Setting all values in an array with arbitrary dimensions

I'm looking for a way to set every value in a multidimensional array to a single value. The problem is that the number of dimensions is unknown at compile-time - it could be one-dimensional, it could be 4-dimensional. Since foreach doesn't let you set values, what is one way that I could achieve this goal? Thanks much.
While this problem appears simple on the surface, it's actually more complicated than it looks. However, by recognizing that visiting every position in a multidimensional (or even jagged) array is a Cartesian product operation on the set of indexes of the array - we can simplify the solution ... and ultimately write a more elegant solution.
We're going to leverage Eric Lippert's LINQ Cartesian Product implementation to do the heavy lifting. You can read more about how that works on his blog if you like.
While this implementation is specific to visiting the cells of a multidimensional array - it should be relatively easy to see how to extend it to visit a jagged array as well.
public static class EnumerableExt
{
// Eric Lippert's Cartesian Product operator...
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(
this IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> emptyProduct =
new[] { Enumerable.Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat(new[] { item }));
}
}
class MDFill
{
public static void Main()
{
// create an arbitrary multidimensional array
Array mdArray = new int[2,3,4,5];
// create a sequences of sequences representing all of the possible
// index positions of each dimension within the MD-array
var dimensionBounds =
Enumerable.Range(0, mdArray.Rank)
.Select(x => Enumerable.Range(mdArray.GetLowerBound(x),
mdArray.GetUpperBound(x) - mdArray.GetLowerBound(x)+1));
// use the cartesian product to visit every permutation of indexes
// in the MD array and set each position to a specific value...
int someValue = 100;
foreach( var indexSet in dimensionBounds.CartesianProduct() )
{
mdArray.SetValue( someValue, indexSet.ToArray() );
}
}
}
It's now trivial to factor this code out into a reusable method that can be used for either jagged or multidimensional arrays ... or any data structure that can be viewed as a rectangular array.
Array.Length will tell you the number of elements the array was declared to store, so an array of arrays (whether rectangular or jagged) can be traversed as follows:
for(var i=0; i<myMDArray.Length; i++)
for(var j=0; j < myMDArray[i].Length; i++)
DoSomethingTo(myMDArray[i][j]);
If the array is rectangular (all child arrays are the same length), you can get the Length of the first array and store in a variable; it will slightly improve performance.
When the number of dimensions is unknown, this can be made recursive:
public void SetValueOn(Array theArray, Object theValue)
{
if(theArray[0] is Array) //we haven't hit bottom yet
for(int a=0;a<theArray.Length;a++)
SetValueOn(theArray[a], theValue);
else if(theValue.GetType().IsAssignableFrom(theArray[0].GetType()))
for(int i=0;i<theArray.Length;i++)
theArray[i] = theValue;
else throw new ArgumentException(
"theValue is not assignable to elements of theArray");
}
I think there is no direct way of doing this, so you'll need to use the Rank property to get the number of dimensions and a SetValue method (that takes an array with index for every dimension as argument).
Some code snippet to get you started (for standard multi-dimensional arrays):
bool IncrementLastIndex(Array ar, int[] indices) {
// Return 'false' if indices[i] == ar.GetLength(i) for all 'i'
// otherwise, find the last index such that it can be incremented,
// increment it and set all larger indices to 0
for(int dim = indices.Length - 1; dim >= 0; dim--) {
if (indices[dim] < ar.GetLength(dim)) {
indices[dim]++;
for(int i = dim + 1; i < indices.Length; i++) indices[i] = 0;
return;
}
}
}
void ClearArray(Array ar, object val) {
var indices = new int[ar.Rank];
do {
// Set the value in the array to specified value
ar.SetValue(val, indices);
} while(IncrementLastIndex(ar, indices));
}
The Array.Clear method will let you clear (set to default value) all elements in a multi-dimensional array (i.e., int[,]). So if you just want to clear the array, you can write Array.Clear(myArray, 0, myArray.Length);
There doesn't appear to be any method that will set all of the elements of an array to an arbitrary value.
Note that if you used that for a jagged array (i.e. int[][]), you'd end up with an array of null references to arrays. That is, if you wrote:
int[][] myArray;
// do some stuff to initialize the array
// now clear the array
Array.Clear(myArray, 0, myArray.Length);
Then myArray[0] would be null.
Are you saying that you want to iterate through each element and (if available) each dimension of an array and set each value along the way?
If that's the case you'd make a recursive function that iterates the dimensions and sets values. Check the Array.Rank property on MSDN and the Array.GetUpperBound function on MSDN.
Lastly, I'm sure generic List<T> has some sort of way of doing this.

Categories

Resources