I want to move all the data from column 0 of a 2D array to a separate 1D array. I have this so far:
for (int x = 0; x < 100; x++) { //100 is the amount of rows in the 2D array
array1D[x] = array2D[x, 0]; //0 is the column I want to take from
}
Is there a more better/more efficient way to achieve the same result?
You cannot copy out the columns, but you can copy out the rows with Buffer.BlockCopy()
class Program
{
static void FillArray(out int[,] array)
{
// 2 rows with 100 columns
array=new int[2, 100];
for (int i=0; i<100; i++)
{
array[0, i]=i;
array[1, i]=100-i;
}
}
static void Main(string[] args)
{
int[,] array2D;
FillArray(out array2D);
var first_row=new int[100];
var second_row=new int[100];
int bytes=sizeof(int);
Buffer.BlockCopy(array2D, 0, first_row, 0, 100*bytes);
// 0, 1, 2, ...
Buffer.BlockCopy(array2D, 100*bytes, second_row, 0, 100*bytes);
// 100, 99, 98, ..
}
}
Update
Here is an extension method do extract a single row from a 2D array (of any type)
public static T[] GetRow<T>(this T[,] array, int rowIndex)
{
int n = array.GetLength(1);
var row = new T[n];
var size = Buffer.ByteLength(row);
Buffer.BlockCopy(array, rowIndex*size, row, 0, size);
return row;
}
to be used as
var array = new double[3, 3] {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7 ,8, 9 } };
var second = array.GetRow(1);
// {4, 5, 6}
Related
This question already has answers here:
Copy single row from multidimensional array into new one dimensional array
(3 answers)
Closed 1 year ago.
Having the following:
int[,] a = new int[4, 2];
int[] b = new int[2];
how do I copy values from b into the first element of a? What's wrong with b.CopyTo(a[0])?
You can access a only by using 2 coordinates (so a[x,y]) because it is defined using 2 dimensions.
Try using int[][] a instead, if you do that then a becomes an array containing 1-dimensional subarrays, and then you can use 1 coordinate to access a subarray.
Example code:
int[][] a = new int[4][];
a[0] = new int[2];
int[] b = new int[2];
Note that after this, when I try do to b.CopyTo(a[0]) I get a "The call is ambiguous " compilation error (in .NET 5) because there two different extension methods that both match the CopyTo signature...
What's wrong with b.CopyTo(a[0])?
A is a two dimensional array, so you need two indices, i.e. a[0,0] = b[0]
Instead of using the built in multidimensional array I would suggest using a wrapper around a 1D array instead, with a indexer something like this:
public T this[int x, int y]
{
get => Data[y * Width + x];
set => Data[y * Width + x] = value;
}
This has the advantage of easier interoperability, since many system exposes 2D buffers of various kinds as 1D data + size. This allows copying data to be done by a block copy instead of copying element by element.
For primitives array types you can define extension methods for packing or unpacking arrays using the Buffer.BlockCopy();
static class Program
{
static void Main(string[] args)
{
int[,] A = new[,] { { 1, 2 }, { 3, 4 } };
int[] data = A.PackMarix();
int[,] B = data.UnPackMarix(2, 2);
Console.WriteLine(B);
}
public static int[,] UnPackMarix(this int[] data, int rows, int columns)
{
int[,] result = new int[rows, columns];
int bytes = Buffer.ByteLength(data);
Buffer.BlockCopy(data, 0, result, 0, bytes);
return result;
}
public static int[] PackMarix(this int[,] data)
{
int[] result = new int[data.Length];
int bytes = Buffer.ByteLength(data);
Buffer.BlockCopy(data, 0, result, 0, bytes);
return result;
}
}
For non-primitive types you have to do the copying manually
public static T[,] UnPackMarix<T>(this T[] data, int rows, int columns)
{
var result = new T[rows, columns];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
result[i, j] = data[i * columns + j];
}
}
return result;
}
public unsafe static T[] PackMarix<T>(this T[,] data)
{
var result = new T[data.Length];
int rows = data.GetLength(0);
int columns = data.GetLength(1);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
result[i * columns + j] = data[i, j];
}
}
return result;
}
This has been posted on SO before but I couldn't find the old post. Anyway, use the Microsoft High Performance toolkit. It has spans for 2D memory. With that you can do this:
int[,] a = new int[4, 2];
int[] b = { 1, 2 };
var spanB = b.AsSpan();
var spanA = a.AsSpan2D();
spanB.CopyTo(spanA.GetRowSpan(0));
foreach (var i in spanA)
Console.WriteLine(i);
I'm trying to find out how to make a 2D array out of possibly normal arrays.
Here is an example how'd I imagine that:
int[,] original = new int[,] {{1,1,1,1}, {1,0,0,1}, {1,0,0,1}, {1,1,1,1}};
int[] part = {1,1,1,1};
int[,] copy = new int[,] {part}, {1,0,0,1}, {1,0,0,1}, {1,1,1,1}};
This is not easy to do in general with native 2d arrays, and impossible to do during initialization.
But you can modify an existing 2d array with the following extension methods.
static class Program
{
static void Main(string[] args)
{
int[,] original = new int[,] {
{ 1, 1, 1, 1 },
{ 1, 0, 0, 1 },
{ 1, 0, 0, 1 },
{ 1, 1, 1, 1 } };
int[] row_0 = original.GetRow(0);
// {1,1,1,1}
int[] part = { 1, 2, 3, 4 };
original.SetRow(0, part);
// {{1,2,3,4},{1,0,0,1},...}
}
public static T[] GetRow<T>(this T[,] matrix, int row)
{
int rows = matrix.GetLength(0);
int columns = matrix.GetLength(1);
T[] result = new T[columns];
if (row<=rows)
{
int size = Buffer.ByteLength(matrix)/rows;
Buffer.BlockCopy(matrix, row*size, result, 0, size);
}
return result;
}
public static void SetRow<T>(this T[,] matrix, int row, params T[] elements)
{
int rows = matrix.GetLength(0);
int columns = matrix.GetLength(1);
if (row<rows && elements.Length == columns)
{
int size = Buffer.ByteLength(elements);
Buffer.BlockCopy(elements, 0, matrix, row*size, size);
}
}
}
Of course, the same functionality is trivial with jagged arrays. Instead of int[,] use int[][].
static class Program
{
static void Main(string[] args)
{
int[][] original = new int[][] {
new int[] { 1, 1, 1, 1 },
new int[] { 1, 0, 0, 1 },
new int[] { 1, 0, 0, 1 },
new int[] { 1, 1, 1, 1 }
};
int[] row_0 = original[0];
// { 1, 1, 1, 1}
int[] parts = new[] { 1, 2, 3, 4 }; // implicit int[] type
original[0] = parts;
// { {1, 2, 3, 4}, {1, 0, 0, 1},..}
int[,] matrix = original.JaggedToMatrix();
}
public static T[,] JaggedToMatrix<T>(this T[][] jagged)
{
int rows = jagged.Length;
int columns = jagged.Length>0 ? jagged[0].Length : 0;
T[,] result = new T[rows, columns];
for (int i = 0; i < rows; i++)
{
result.SetRow(i, jagged[i]);
}
return result;
}
public static T[][] MatrixToJagged<T>(this T[,] matrix)
{
int rows = matrix.GetLength(0);
int columns = matrix.GetLength(1);
T[][] result = new T[rows][];
for (int i = 0; i < rows; i++)
{
result[i] = matrix.GetRow(i);
}
return result;
}
public static T[] GetRow<T>(this T[,] matrix, int row)
{
int rows = matrix.GetLength(0);
int columns = matrix.GetLength(1);
T[] result = new T[columns];
if (row<=rows)
{
int size = Buffer.ByteLength(matrix)/rows;
Buffer.BlockCopy(matrix, row*size, result, 0, size);
}
return result;
}
public static void SetRow<T>(this T[,] matrix, int row, params T[] elements)
{
int rows = matrix.GetLength(0);
int columns = matrix.GetLength(1);
if (row<rows && elements.Length == columns)
{
int size = Buffer.ByteLength(elements);
Buffer.BlockCopy(elements, 0, matrix, row*size, size);
}
}
}
Let's say i have an array of 6 elements of int type.
It looks like this
var array = new int [] { 0, 1, 2, 3, 4, 5 };
How can I randomly shuffle my array ensuring every index have a new value.
// Bad
// The number at index 3 did not change and still has a value of 3
new int [] { 1, 0, 5, 3, 2, 4 }
// Good:
// All the index have a new value
new int [] { 4, 2, 0, 5, 3, 1 }
I've tried to Shuffle, but sometimes some values will have the same index position
You could iterate over the array and always swap with a randomly choosen index which is bigger than the current one. That way the numbers get shuffled, but no element can be shuffled back.
Edit: This acutally works, try it:
using System;
class Program {
private static Random rnd = new Random();
public static void Main() {
for (var i = 0; i < 10000; i++) {
int[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Shuffle(array);
Console.WriteLine(String.Join(", ", array));
}
}
public static void Shuffle(int[] array) {
for (var i = 0; i + 1 < array.Length; i++) {
// generate j so that i < j < length
int j = rnd.Next(i + 1, array.Length);
// swap elements at i and j
var tmp = array[j];
array[j] = array[i];
array[i] = tmp;
// check
if (array[i] == i) {
throw new Exception(":(");
}
}
}
}
Also its very similar to Sattolo's algorithm, which would also work.
I have a 2D string array.
I just want to randomize the rows order and shuffle the items within each row.
So for example:
[1,2
3,4]
I want it to be as below, row pairs stay same here (order change is valid):
[4,3
1,2] or
[3,4
2,1] or
[4,3
2,1] or
[1,2
3,4] or
[2,1
3,4] or
[2,1
4,3] or
[3,4
1,2]
and i want to avoid below shuffling because i'll read my array row by row, i want to keep my rows to contain same elements. I want to keep my row pairs. Below, my [1,2] and [3,4] rows does not exist anymore :
[1,3
2,4] or
[3,1
4,2] or
[3,1
2,4] or
[1,4
2,3] ....
So here is my array:
array_to_shuffle = new string[len_2d,2];
Shuffle(array_to_shuffle);
and the function i need help :
public void Shuffle(Random rand, string[,] array)
{
rand = new Random();
int[] randomised_array = new int[len_2d];
for (int i = 0; i < len_2d; i++)
{
randomised_array[i] = i;
}
int[] MyRandomArray = randomised_array.OrderBy(x => rand.Next()).ToArray();
string tmp1 = String.Empty;
string tmp2 = String.Empty;
array[MyRandomArray[0], 0] = tmp1;
array[MyRandomArray[0], 1] = tmp2;
array[MyRandomArray[0], 0] = array[MyRandomArray[1],0];
array[MyRandomArray[0], 1] = array[MyRandomArray[1],1];
array[MyRandomArray[1], 0] = tmp2;
array[MyRandomArray[1], 1] = tmp1;
}
Thank you everyone...
Try this code (necessary comments are in code):
static void Main(string[] args)
{
int[,] matrix = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 9, 10 }, { 11, 12 } };
matrix = Shuffle(matrix);
}
static T[,] Shuffle<T>(T[,] matrix)
{
int howManyRows = matrix.GetLength(0);
int howManyColumns = matrix.GetLength(1);
T[,] randomizedMatrix = new T[howManyRows, howManyColumns];
//we will use those arrays to randomize indexes
int[] shuffledRowIndexes = Enumerable.Range(0, howManyRows).ToArray();
int[] shuffledColumnIndexes = Enumerable.Range(0, howManyColumns).ToArray();
Random rnd = new Random();
shuffledRowIndexes = shuffledRowIndexes.OrderBy(x => rnd.Next()).ToArray();
for (int i = 0; i < howManyRows; i++)
{
// at every loop we get new randomized column idexes, so every row will be shuffled independently
shuffledColumnIndexes = shuffledColumnIndexes.OrderBy(x => rnd.Next()).ToArray();
for (int j = 0; j < howManyColumns; j++)
randomizedMatrix[i, j] = matrix[shuffledRowIndexes.ElementAt(i), shuffledColumnIndexes.ElementAt(j)];
}
return randomizedMatrix;
}
Helpful articles:
Best way to randomize an array with .NET
What are the differences between a multidimensional array and an array of arrays in C#?
How to delete a specific row and column from 2D array in C#?
int[,] array= {{1,2,3},{4,5,6},{7,8,9}};
lets say I want to delete row i and column i (skipping them) ... for nXn array not just 3x3 and store the remaining array in a new array...
so the output would be:
{5,6},{8,9}
There's no built-in way to do that, you can do it yourself:
static void Main()
{
int[,] array = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
var trim = TrimArray(0, 2, array);
}
public static int[,] TrimArray(int rowToRemove, int columnToRemove, int[,] originalArray)
{
int[,] result = new int[originalArray.GetLength(0) - 1, originalArray.GetLength(1) - 1];
for (int i = 0, j = 0; i < originalArray.GetLength(0); i++)
{
if (i == rowToRemove)
continue;
for (int k = 0, u = 0; k < originalArray.GetLength(1); k++)
{
if (k == columnToRemove)
continue;
result[j, u] = originalArray[i, k];
u++;
}
j++;
}
return result;
}
No, arrays don't let you do that. You could make your own data structure for that, but it's not going to be exactly simple (unlike if you only wanted to be able to remove rows, for example).
For simple operations, it would be quite enough to build a class on top of an underlying array, and handle the re-indexing to map the virtual 2D array to the physical array underneath. But it's going to get a bit tricky as you combine removals and additions, and deform the array overall.
Very simple logic. Just play with the loop:
int[,] array = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int[,] arrayskip = new int[array.GetLength(0) - 1, array.GetLength(1) - 1];
for (int i = 1; i < array.GetLength(0); i++)
{
for (int j = 1; j < array.GetLength(1); j++)
{
arrayskip[i - 1, j - 1] = array[i, j];
}
}
I created this method, have a look
public static double[,] fillNewArr(double[,] originalArr, int row, int col)
{
double[,] tempArray = new double[originalArr.GetLength(0) - 1, originalArr.GetLength(1) - 1];
int newRow = 0;
int newCol = 0;
for (int i = 0; i < originalArr.GetLength(0); i++)
{
for (int j = 0; j < originalArr.GetLength(1); j++)
{
if(i != row && j != col)
{
tempArray[newRow, newCol] = originalArr[i, j];
newRow++;
newCol++;
}
}
}
return tempArray;
}
having some out of range, It's obvious why but I'm trying to get there...