Getting a 1D array from a 3D array C# - c#

I have a 8x8x3 array with some values. What I want to do is make a list of just the 1D arrays.
What I've got so far:
int[] packIt(int[,,] data, int factor) {
List<int[]> toReturn = new List<int[]>();
int[] test = data[0, 0];
So unless I'm missing something, I make a list of one dimensional arrays and try to fit in the one dimensional array at data[0, 0] (the test is just a placeholder so far). The error I'm getting is "Wrong number of indices", however if I follow the data[0,0,0] (which gives no error) I'll just get the 1 value at the location. I could do it manually, but am just wondering if there is an implementation for the functionality that I'm trying to do, as I will be using it a lot. Thanks a bunch.

You don't need to do anything specific to turn a 3D array into a 1D one; you can just enumerate it:
foreach(var x in multiDim)
...
This will print 1 to 8:
var x = new int[2,2,2];
x[0,0,0] = 1;
x[0,0,1] = 2;
x[0,1,0] = 3;
x[0,1,1] = 4;
x[1,0,0] = 5;
x[1,0,1] = 6;
x[1,1,0] = 7;
x[1,1,1] = 8;
foreach(int i in x)
Console.WriteLine(i);
To this end you can just straight enumerate your array in chunks of whatever:
var out = new List<int[]>();
var arr = new int[chunkSize];
out.Add(arr);
var idx = 0;
foreach(var x in miltiDimArray){
if(idx == chunkSize){
out.Add(arr = new int[chunkSize]);
idx = 0;
}
arr[idx++] = i;
}
Note that I don't try to make the ticks array smaller if the chunk size doesn't divide into the number of elements. idx will have a residual value you can use to work out what to resize the last array by if that is important

Related

How to append arrays in c#

I would like to get the output of this to be [1,2,3,4,...,200]. Any suggestions for how to go about this?
var Laser_data = 0;
var i = 0;
var j = 1;
int[] LaserData_200 = new int[200];
for (i = 0; i < LaserData_200.Length; i++)
{
Laser_data += j;
LaserData_200[i] = Laser_data;
Console.WriteLine(" " + LaserData_200[i]);
}
Current output:
1
2
3
4
ect.
Your array initialization and element assignment can be simplified massively. Your array is just the numbers 1 through 200 (inclusive). Enumerable.Range can generate that for you, then save it as an array.
int[] myArray = Enumerable.Range(1, 200).ToArray();
To print it all, string.Join it using a comma as a seperator.
Console.WriteLine($"[{string.Join(',', myArray)}]");
// [1,2,3,4,5,6,7,8,9,10,11,12,13, .... 200]
I see the title has nothing to do with the posted code.
So I am answering the question in the title.
Say you have two arrays a and b and you want to create a third array that combines the two arrays, then you write code like
int[] c = Enumerable.Concat(a, b).ToArray();
or you have and array a and you want to keep adding values to it in loop. When arrays are fixed size (a.IsFixedSize = true always) so you can do this efficiently.
The best solution is to use List<T> instead of an array
List<int> a = new List<int>()
for(int i=0; i<200; i++)
{
a.Add( i+1 );
}
and if you want an array in the end, you just do
int[] c= a.ToArray();

check if 2d array contains value on second spot

I have a 2D array for a lottery I am creating. Basically it's a set of 2 integers:
int[,] coupon = new int[rowAmount, numAmount];
Where rowAmount is the amount of rows, and numAmount is the amount of numbers in that row.
Now I need to select the numbers for each row, however there may not be duplicates of a number within a specific row.
for (int r = 0; r < rowAmount; ++r)
{
for (int n = 0; n < numAmount; ++n)
{
userNum = lotRng.Next(1, numAmount * rngMult);
while (COUPON CONTAINS DUPLICATE NUMBER ON SECOND SPOT )
{
userNum = lotRng.Next(1, numAmount * rngMult);
}
coupon[r, n] = userNum;
}
}
My issue is the while part, I cannot figure out how to check if coupon contains the userNum on the second slot(The numAmount slot). For lists and stuff I used to just do list.Contains() but that doesn't seem to work on here.
Depending on the size of your array is wether it makes sense to optimize performance.
Depending on that one possibility would be to sort the array and use Array.BinarySearch .
You have to sort your array for that.
https://msdn.microsoft.com/en-us/library/2cy9f6wb(v=vs.110).aspx
So you have a number of possibilities to optimize data structure.
Solution with an array of lists is one of my favourites for this. It's very similar to my other with jagged arrays but faster- because List search is most efficient and Linq searches are not.
const int rowAmount = 1000;
const int numAmount=1000;
const int rngMult = 10;
Random lotRng = new Random();
var coupon = new List<int>[rowAmount];
int userNum;
for (int r = 0; r < rowAmount; r++)
{
coupon[r]= new List<int>();
for (int n = 0; n < numAmount; ++n)
{
do userNum = lotRng.Next(1, numAmount * rngMult);
while (coupon[r].Contains(userNum));
coupon[r].Add(userNum);
}
}
Of course it would be also possible to use a list of lists (kind of 2D lists), if necessary.
var couponLoL = new List<List<int>>();
The following quick and dirty way show a possible way of copying a 2D array to a list, but not to recommend here for several reasons (loop, boxing for value types):
var coupon= new int[rowAmount,numAmount];
[..]
do userNum = lotRng.Next(1, numAmount * rngMult);
while (coupon.Cast<int>().ToList().Contains(userNum));
In this special case it makes even less sense, because this would look in the whole 2D array for the double value. But it is worth knowing how to convert from 2D to 1D array (and then in a list).
Solution with 2D jagged arrays: If you want to access rows and columns in C#, a jagged array is very convenient and unless you care very much how effient the array ist stored internally, jagged array are to recommend strongly for that.
Jagged arrays are simply arrays of arrays.
const int rowAmount = 1000;
const int numAmount=1000;
const int rngMult = 10;
int userNum;
Random lotRng = new Random();
var coupon = new int[rowAmount][];
for (int r = 0; r < rowAmount; r++)
{
coupon[r] = new int[numAmount];
for (int n = 0; n < numAmount; ++n)
{
do userNum = lotRng.Next(1, numAmount * rngMult);
while (Array.Exists(coupon[r], x => x == userNum));
coupon[r, n] = userNum;
}
}
The above function Array.Exists works only for 1 dimension what is enough here, and needs no Linq. The same as above with Linq method .Any :
while (coupon[r].Any(x => x == userNum));
If you would have to search in two dimensions for a double value, you would need a loop more again, but still on nested loop level less than without this.
Linq is elegant, but normally not the fastest method (but you would have to handle with very big arrays of multi-million sizes for that to matter).
For other possibilities of using Linq, look for example here:
How to use LINQ with a 2 dimensional array
Another idea would be to make one-dimensional array of size rowAmount*numAmount.
It needs a little bit of thinking, but allows most simple and fastest access of searching.
Solution with loops in an array. Not elegant, but you could refactor the search loops in an own method to look better. But as a second point, in this case a linear search like shown is not a really fast solution either.
Only inner part of the 2 for-loops, not full code (as in other answers by me here):
bool foundDup;
do
{
userNum = lotRng.Next(1, numAmount * rngMult);
foundDup = false;
for (var x = 0; x < coupon.GetLength(1); x++) //Iterate over second dimension only
if (coupon[r, x] == userNum)
{ foundDup = true;
break;
}
} while (foundDup);
coupon[r, n] = userNum;
In the special context of this question, you can optimize the loop:
for (var x = 0; x < n; x++)
As you say in your comment you need to check all n fields vs. your new userNum. You can solve this with the following code:
for (int r = 0; r < rowAmount; ++r)
{
for (int n = 0; n < numAmount; ++n)
{
userNum = lotRng.Next(1, numAmount * rngMult);
for (int x = 0; x < coupon.GetLength(1); x++) //Iterate over your second dimension again
{
while (coupon[r,x] == userNum)
{
userNum = lotRng.Next(1, numAmount * rngMult);
}
}
coupon[r, n] = userNum;
}
}

Get a random value from a two dimensional array

The way I get a value from a single dimensional array is:
Random random = new Random();
getit = w[r.Next(0, w.Length)];
Can you please tell me how do I do the same for two dimensional array?
To ensure that you have an even distribution you shouldn't be generating multiple random numbers. Calculate the total possible number of values by multiplying the lengths of the dimensions, choose an index, and then find the one item that corresponds to that index:
public static T GetRandomValue<T>(T[,] array, Random random)
{
int values = array.GetLength(0) * array.GetLength(1);
int index = random.Next(values);
return array[index / array.GetLength(0), index % array.GetLength(0)];
}
Assuming you have a simple two-dimensional array [,]1, not a jagged array [][], then you can use the Array.GetLength method to get the length of each array dimension. For example:
Random random = new Random();
string[,] arr = new string[10, 10];
int i1 = r.Next(0, arr.GetLength(0));
int i2 = r.Next(0, arr.GetLength(1));
string value = arr[i1, i2];
1) It is possible for the lower bound of a multi-dimensional array to be different from the default of 0. In that case, use the Array.GetLowerBound method appropriately.
If you have a jagged array instead [][], not a real two-dimensional array [,], then you can do it sequentially:
Random random = new Random();
string[][] arr = new string[][10];
for (int i = 0; i < arr.Length; i++)
arr[i] = new string[10];
int i1 = r.Next(0, arr.Length);
string[] subarr = arr[i1];
int i2 = r.Next(0, subarr.Length);
string value = subarr[i2];
Not really the fastest method, but you could also do this with a bit of Linq:
var totalSize = Enumerable.Range(0, array.Rank).Aggregate(0, (l, r) => l * array.GetLength(r));
var getit = w.ElementAt(r.Next(0, totalSize));
This works for arrays of any dimension.

C# Dynamic multidimensional array

I have a function...
private double[,] AddToArray(double[,] array, double[] dataToAdd)
{
// Make a new row at the end of 'array' and copy values
// from 'dataToAdd' into the new row.
//
// Return the new, modified array.
}
However 'double[,]' isn't dynamic and I dont know what the final size of the array will be. I can create a List from it and add the new row to the list, but then I cant seem to convert it back to a double[,]. The List.ToArray() wants to output a jagged array (double[][]). This wont work. I'm interfacing with a program developed in LabVIEW and LV refuses to accept a jagged array. LV is happy with a fixed array ([,]).
Any help?
You could try this:
private double[,] AddToArray(double[,] array, double[] dataToAdd)
{
var dim0 = array.GetLength(0);
var dim1 = array.GetLength(1);
if (dim1 != dataToAdd.Length) throw new ArgumentException();
var na = new double[dim0 + 1, dim1];
Array.Copy(array, na, array.Length);
for (var i = 0; i < dim1; ++i) na[dim0, i] = dataToAdd[i];
return na;
}
It explicitly increments the high-order dimension by one, and also verifies that the length of the low-order dimension is equal to the dataToAdd array. I have not been able to any smarter copying from dataToAdd to the 2D array than by a for loop; it is not possible to apply Array.Copy for different ranked arrays.
You could always create the 2-dimensional array manually:
double[,] array = new double[list.Count, data.Length];
for(int i = 0;i < list.Count;++i)
for(int j = 0;j < data.Length;++j)
array[i, j] = list[i][j];
That is, of course, assuming that all of the 'dataToAdd' is of uniform length. Otherwise, what do you fill in the array for unused elements?

I am working with arrays and need to sort the array. This array keeps showing out of range exceptions

I have established an array and a large textbox which displays the array. Basically, you enter a name, 4 quarterly sales figures and it calculates the yearly total. I am now starting on the sort button. This would sort given columns numbers from most to least. I have gotten an if statement that looks like it should work for column five (the total column). I keep getting an out of range exception and am not sure why. Any ideas out there? I am sure this is a simple problem I am not seeing.
do {
swapFlag = false;
for (n=0; n < lastIndexUsed; n++)
{
if (quarters[n, sortCol] < quarters[n+1, sortCol])
{
//Column 5
temp = quarters[n,5];
quarters[n,5] = quarters[n +1, 3];
quarters[n +1, 3] = temp;
//swapflag
swapFlag = true;
}
}
} while (swapFlag);
This shows how I get 0-5 for sortCol:
if (rbRegion.Checked)
sortCol = 0;
if (rb1.Checked)
sortCol = 1;
if (rb2.Checked)
sortCol = 2;
if (rb3.Checked)
sortCol = 3;
if (rb4.Checked)
sortCol = 4;
if (rbTotal.Checked)
sortCol = 5;
Button Variables:
int n;
int temp;
int sortCol = 0;
string ntemp;
bool swapFlag;
Global Variables
int lastIndexUsed = -1;
int[,] quarters = new int[10, 5];
string[] Branch = new string[10];
quarters is defined as
int[,] quarters = new int[10, 5];
since arrays are zero based this gives you index 0...4 on the second dimension but you are trying to access index 5:
temp = quarters[n,5];
It seems to me, that you could have n = quaters.size - 1, and therefore n + 1 = quaters.size.
So it gets out of array's bound.
I smell the problem is with these:
quarters[n+1, sortCol]
quarters[n+1, 3]
Make sure n+1 is a valid index. What if lastIndexUsed itself is the maximum valid index? Then n+1 would cause IndexOutOfRangeException.
I'd suggest to use more instances of List<int> quartersSortCol0 and use if (rbRegion.Checked) quartersSortCol0.Sort() and avoid ineffective constructions like your "while-for" above. While you can use overload of Sort method with custom comparison.

Categories

Resources