Convert multi-dimension array to string - c#

I have a 3 dimensional char array initialized as such:
char[,,] cube = new char[10, 10, 10];
It's completely filled and I want to convert its contents to a single string. My current method is this:
for (int z = 0; z < 10; z++) {
for (int y = 0; y < 10; y++) {
for (int x = 0; x < 10; x++) {
build += cube[z, y, x];
}
}
}
Attempting to do build = new string(cube) gives an error:
cannot convert from 'char[*,*,*]' to 'char*'
The for loops are incredibly fast, completing in less than a millisecond on my setup (from 1500 to 4000 ticks). Wondering if a single line method exists that will accomplish the same thing that these nested for loops are doing?
EDIT:
This code will only be used once in the entire program, so I don't need something reusable.

LINQ is your friend.
A multidimensional array implements IEnumerable but sadly apparently not IEnumerable<T>. So first we need to get an IEnumerable<T> to be able to make full use of LINQ. Luckily, we know in this case, that every item in that multidimensional array is of typechar, we just need to tell that to the compiler.
Next, to create a string, there is a convenient constructor, that accepts a char[]. And getting a char[] from an IEnumerable<char> is just one ToArray() away.
Put that together and you get:
using System.Linq;
var build = new string(cube.OfType<char>().ToArray());

This is easier than you think:
public static String FlattenToString(this char[,,] array)
{
var builder = new StringBuilder();
foreach(var #char in array)
{
builder.Append(#char);
}
return builder.ToString();
}
var cube = new char[2,2,2];
cube[0,0,0] = 'a';
cube[0,0,1] = 'b';
cube[0,1,0] = 'c';
cube[0,1,1] = 'd';
cube[1,0,0] = 'e';
cube[1,0,1] = 'f';
cube[1,1,0] = 'g';
cube[1,1,1] = 'h';
Console.WriteLine(cube.FlattenToString());
Prints out abcdefgh.

string build = string.Concat(cube.Cast<char>());
Probably not needed in your case, but a much faster alternative is copying to char[] :
//var cube = new[, ,] { { { 'a', 'b' }, { 'c', 'd' } }, { { 'e', 'f' }, { 'g', 'h' } } };
char[] temp = new char[cube.Length];
Buffer.BlockCopy(cube, 0, temp, 0, temp.Length * sizeof(char));
string build = new string(temp);

char[,,] cube = new char[10, 10, 10];
for (int z = 0; z < 10; z++)
{
for (int y = 0; y < 10; y++)
{
for (int x = 0; x < 10; x++)
{
cube[z, y, x] = (char)(65+x);
}
}
}
/* Just Filling data in array*/
var s1 = cube.OfType<char>().ToList();
string s = string.Join("",s1);

Related

Curve fitting to a 3D polynomial with variable powers

I have 3 data sets. 2 for polynomial itself (let's call them x and y) and 1 for the function value (it's gonna be z).
Polynomial looks something like this (assuming the power of both dimensions is 3):
z = a00 + a01*x + a02*x^2 + a03*x^3 + a10*y + a11*y*x + a12*y*x^2 ... etc
I need to be able to set the power of each dimension when preparing for approximation of values of "a".
I don't really get how CurveFitting functions work with Math.NET Numerics, but i've tried Fit.LinearMultiDim and MultipleRegression.QR. I'm having trouble with initializing the Func delegate
var zs = new double[]
{
//values here
};
var x = new double[]
{
//values here
};
var y = new double[]
{
//values here. But the amounts are equal
};
var design = Matrix<double>.Build.DenseOfRowArrays(Generate.Map2(x, y,(t, w) =>
{
var list = new List<double>(); //Can i get this working?
for (int i = 0; i <= 3; i++)
{
for (int j = 0; j <= 3; j++)
{
list.Add(Math.Pow(t, j)*Math.Pow(w, i));
}
}
return list.ToArray();
}));
double[] p = MultipleRegression.QR(design, Vector<double>.Build.Dense(zs)).ToArray();
So ideally i need to be able to compose the function with some sort of loop that accounts for the max power of both variables.
UPD: The function is always above zero on any axis
I think i got it working.
Here's the code:
List<Func<double[], double>> ps = new List<Func<double[],double>>();
for (int i = 0; i <= polynomialOrderFirstVal; i++)
{
for (int j = 0; j <= polynomialOrderSecVal; j++)
{
var orderFirst = j;
var orderSecond = i;
ps.Add(d => Math.Pow(d[0], orderFirst) * Math.Pow(d[1],orderSecond));
}
}
var psArr = ps.ToArray();
double[] coefs = Fit.LinearMultiDim(x, y, psArr);

Adding ints from to string to 2D array every Nth character

What I am trying to do here is populate a 2d array from a text file. For sake of simplicity, I will keep this short and show you my problem. I have this following string:
string numbers = "11121314151617181920";
I would like to add this to an array every 2 Chars, so the array would appear and output:
11,12,13,14,15,16,17,18,19,20
I have gone about this using the Substring method available in c#. This is my code:
int[,] numArray = new int[1, 10];
for (int x = 0; x < 10; x++)
{
while (i != 20)
{
numArray[0, x] = int.Parse(numbers.Substring(i, 2));
i += 2;
}
}
Edit: The output of this code gives me:
20000000000
My desired output is:
11,12,13,214,15,16,17,18,19,20
Solved it! I had the for loop in the wrong spot:
while (i != 20)
{
for (int x = 0; x < 10; x++)
{
numArray[0, x] = int.Parse(numbers.Substring(i, 2));
i += 2;
}
}

Multi-dimensional foreach loop

How can I properly do so that a check is performed for each string?
My code looks like :
string[,] screeny_baza = new string[300, 300];
for (int i = 0; i < 299; i++)
{
try
{
string nazwa_screna_pokolei = screeny_baza[0,i]
}
catch { };
}
As i see i want to do just it one by one. Is it possible to do it faster omitting values ​​that do not exist or have not been declared? They are just null i think.
I have dimension that looks like to 300/300 .
X0 X1 X2
Y0 00 10 20
Y1 01 11 21
Y2 02 12 22
And want to save just string to each of dimesnion for example
string [00] = "bird";
string [01] = "bird2";
and later need to get this values in loop ( omitting values ​​that do not exist or have not been declared)
Thanks for help.
I don't know about foreach loops on multi dimensional arrays but you can always do this:
string[,] screeny_baza = new string[300, 300];
for (int x = 0; x < screeny_baza.GetLength(0); x++)
{
for (int y = 0; y < screeny_baza.GetLength(1); y++)
{
try
{
string nazwa_screna_pokolei = string.empty;
if (screeny_baza[x, y] != null)
nazwa_screna_pokolei = screeny_baza[x, y];
}
catch { };
}
}
You can foreach on a 2d array. You can even LinQ Where to filter it.
var table = new string[20, 20];
table[0, 0] = "Foo";
table[0, 1] = "Bar";
foreach (var value in table.Cast<string>().Where(x =>!string.IsNullOrEmpty(x))) {
Console.WriteLine(value);
}
Actually your try-catch block will not raise any exception because when you construct the array:
string[,] screeny_baza = new string[300, 300];
you can always index it as long as the indexes are in range; so the statement:
string nazwa_screna_pokolei = screeny_baza[0,i];
will execute without error. Just nazwa_screna_pokolei will be null;
Also if speed is concerned, a nested for-loop is much faster than LinQ. at least for this simple check. for example:
var list = screeny_baza.Cast<string>().Where(x => !string.IsNullOrEmpty(x)).ToList();
will take about 10 milliseconds, but
for (int i = 0; i < 300; i++)
{
for (int j = 0; j < 300; j++)
{
if (string.IsNullOrEmpty(screeny_baza[i,j]))
{
continue;
}
list.Add(screeny_baza[i, j]);
}
}
will take only 1 millisecond.
For storing you would use row and column indices like:
screeny_baza[0,0] = "bird";
screeny_baza[0,1] = "bird";
For looping the values you use GetLength (though you know the dimensions as constant, this is a more flexible way):
for (int row = 0; row < screeny_baza.GetLength(0); row++) {
for (int col = 0; col < screeny_baza.GetLength(1); col++) {
if (!string.IsNullOrEmpty(screeny_baza[row,col])) // if there is a value
Console.WriteLine($"Value at {row},{col} is {screeny_baza[row,col]}");
}
}
My simple helper for such cases
private static void forEachCell(int size, Action<int, int> action)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
action(j, i);
}
}
}
It can be modified to use different sizes.
Usage example:
double totalProbability = 0;
forEachCell(chessboardSize, (row, col) =>
totalProbability += boardSnapshots[movesAmount][row, col]);
return totalProbability;

(jagged array) Array of an Array: automatically create in while loop, how to initialize?

I would like to create an array of an array from a text file...
There are 20000 line with 21 strings in each line separated by ',' .
I would like to read each line and make it into an array , each line being a new array within.
So I wanted to create the jagged array by starting it like this:
string[][] SqlArray = new string[200000][21];
But it gives: ERROR MESSAGE : Invalid rank specifier: expected ',' or ]
How would I create this array or initialize it?
I will be populating the data in the array like this:
while (true)
{
string theline = readIn.ReadLine();
if (theline == null) break;
string[] workingArray = theline.Split(',');
for (int i = 0; i < workingArray.Length; i++)
{
for (int k = 0; k < 20; k++)
{
SqlArray[i][k] = workingArray[k];
}
}
}
Thank you
That type of initialization only works in Java. You must declare an array of arrays then initialize each in a loop.
string[][] SqlArray = new string[21][];
for(int index = 0; index < SqlArray.Length; index++)
{
SqlArray[index] = new string[2000000];
}
Alternatively, you can use a non-jagged array. It will probably work for what you need.
string[,] SqlArray = new string[21 , 2000000];
It can be accessed like so:
SqlArray[2,6264] = x;
To anyone who is interested this is how I ended up implementing it:
TextReader readIn = File.OpenText("..\\..\\datafile.txt");
string[][] SqlArray = new string[rowNumCreate][];
int e = 0;
while (true)
{
string theline = readIn.ReadLine();
if (theline == null) break;
string[] workingArray = theline.Split(',');
SqlArray[e] = new string[valuesInRow +1];
for (int k = 0; k < workingArray.Length; k++)
{
SqlArray[e][k] = workingArray[k];
}
e++;
}
The file being read is a simple mock database set as a flat file that was auto-generated to test an algorithm that I am implementing, which works with jagged arrays; hence instead of working with a data base I just created this for ease of use and to increase and decrease size at will.
Here is the code to build the text file:
Random skill_id;
skill_id = new Random();
// int counter =0;
string seedvalue = TicksToString();
int rowNumCreate = 200000;
int valuesInRow = 20;
string lineInFile = seedvalue;
string delimiter = ",";
for (int i = 0; i < rowNumCreate; i++)
{
for (int t = 0; t < valuesInRow; t++)
{
int skill = skill_id.Next(40);
string SCon = Convert.ToString(skill);
lineInFile += delimiter + SCon;
}
if (rowNumCreate >= i + 1)
{
dataFile.WriteLine(lineInFile);
lineInFile = "";
string userPK = TicksToString();
lineInFile += userPK;
}
}
dataFile.Close();
public static string TicksToString()
{
long ms = DateTime.Now.Second;
long ms2 = DateTime.Now.Millisecond;
Random seeds;
seeds = new Random();
int ran = seeds.GetHashCode();
return string.Format("{0:X}{1:X}{2:X}", ms, ms2, ran).ToLower();
}
I am still a student so not sure if the code is A-grade but it works :)

How to copy C# 3D jagged array

I need to (initially) copy a C# 3D jagged array, foos, to another 3D array (and eventually add x, y, z dimensions). I thought I could use the same syntax/logic to copy foos as was used to build foos as I've done below (where row = 2, col = 3, z = 4):
private static void copyFooArray(Foo[][][] foos, ref Foo[][][] newArray)
{
for (int row = 0; row < foos.Length; row++)
{
newArray[row] = new Foo[foos[row].Length][];
for (int col = 0; col < foos[row].Length; col++)
{
newArray[row][col] = new Foo[foos[row][col].Length];
for (int z= 0; z< foos[row][col].Length; z++)
{
newArray[row][col][z] = new Foo();
newArray[row][col][z].member = foos[row][col][z].member;
}
}
}
Console.Read();
}
but I'm getting Index was outside the bounds of the array. on this line:
newArray[row] = new Foo[foos[row].Length][];
Why?
Foo Class:
public class Foo
{
public string member;
}
Thanks.
It doesn't look like your referenced array is being initialized properly. In order to set the value, your newArray must be initialized as the same size of your original.
For this to work you'd need to pass in something like this:
Foo[][][] firstFoo = new Foo[10][][];
Foo[][][] fooToCopy = new Foo[firstFoo.Length][][];
copyFooArray(firstFoo, ref fooToCopy);
Also, the ref keyword is unnecessary since arrays are passed by reference in c# anyways.
In addition to the fix presented in the accepted answer, here's a faster way to do that:
public static int[][][] Copy(int[][][] source)
{
int[][][] dest = new int[source.Length][][];
for (int x = 0; x < source.Length; x++)
{
int[][] s = new int[source[x].Length][];
for (int y = 0; y < source[x].Length; y++)
{
int[] n = new int[source[x][y].Length];
int length = source[x][y].Length * sizeof(int);
Buffer.BlockCopy(source[x][y], 0, n, 0, length);
s[y] = n;
}
dest[x] = s;
}
return dest;
}

Categories