Mathnet numerics indexing parts of a matrix - c#

Using Math.Net Numerics, how can I index parts of a matrix?
For example, I have a collection of ints and I want to get a submatrix with the rows and columns chosen accordingly.
A[2:3,2:3] should give me that 2 x 2 submatrix of A where the row index and the column index is either 2 or 3

Just use some thing like
var m = Matrix<double>.Build.Dense(6,4,(i,j) => 10*i + j);
m.Column(2); // [2,12,22,32,42,52]
to access the desired column use the Vector<double> Column(int columnIndex) extension method.

I suspect you were looking for something like this Extension method.
public static Matrix<double> Sub(this Matrix<double> m, int[] rows, int[] columns)
{
var output = Matrix<double>.Build.Dense(rows.Length, columns.Length);
for (int i = 0; i < rows.Length; i++)
{
for (int j = 0; j < columns.Length; j++)
{
output[i,j] = m[rows[i],columns[j]];
}
}
return output;
}
I've omitted the exception handling to ensure rows and columns are not null.

Related

Convert multi-dimensional array to multi-dimensional dictionary

How do I convert a multi-dimensional array of int into a multi-dimensional dictionary using Lambda?
For example I would like to convert Test1 (int[2,3]) into Test 3 (Dictionary<(int,int),int>)
int[,] Test1 = new int[2, 3];
int k = 0;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
Test1[i, j] = k++;
}
}
I can easily convert it into dictionary using the traditional way with the "for - next" loop but when I tried using lambda:
Dictionary<(int,int),int>Test3 = Enumerable.Range(0, Test1.Length)
.ToDictionary((int i ,int j )=>new { z =Test1[i, j] });
I got the syntax error below:
Error CS0411 The type arguments for method 'Enumerable.ToDictionary<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
How do I specify the type arguments explicitly?
Unfortunately you can't easily use Linq to loop through "rows" of a 2-D array, since the iterator for a square array just loops through the elements. You'll need to use an old-fashion for loop:
var Test3 = new Dictionary<(int,int),int>();
for (int i = 0; i < Test1.GetLength(0); i++)
{
Test3[(Test1[i, 0], Test1[i, 1])] = Test1[i, 2];
}
This assumes that the pairs in the first two "columns" are unique, otherwise the last one would "win".
You could use Linq to enumerate through the rows by usinng Range over one axis as you tried to do:
Dictionary<(int,int),int>Test3 = Enumerable
.Range(0, Test1.GetLength(0))
.ToDictionary(i => (Test1[i, 0], Test1[i, 1]), i => Test1[i, 2]);
Note that the lambdas in ToDictionary define the key and value, respectively.
but the for loop is cleaner and easier to understand in my opinion.

How to combine multiple arrays (that represent columns of data) into a nested/jagged array (or even a 2D) array

I have a program that I'm writing to extract certain data from various excel spreadsheet.
The process so far is:
for each spreadsheet identified:
-read in the data as a multidimensional array using interop excel (Even though it is slow, it is the best choice due to all of the different file formats I need to read in)
Sample: object[,] cellValues = (object[,])range.Value2;
-Identify the columns that I actually need and what order I need them in. This is stored in a jagged array of bytes:
byte[][] targetColumns
-THe jagged array essentially is (columnIndexFromSpreadsheet, preferredColumnOrder) e.g. if the first column in the spreadsheet should be read in as column 10 it would be (1, 10)
-I sort the jagged array by the preferred column order (that way I can just loop through the array in that order and extract those columns):
public static byte[][] SortTargetColumns(byte[][] targetColumns)
{
return targetColumns.OrderBy(x => x.Skip(1).First()).ToArray();
}
-I then extract that column by creating an array from that column index of the multidimensional array. This is the method that is called:
public static object[] ExtractColumn(object[,] dataArray ,byte columnIndex)
{
return Enumerable.Range(ArrayIndexStart, dataArray.GetLength(0)).Select(x => dataArray[x, columnIndex]).ToArray();
}
Usage:
array = ExtractColumn(dataArray, (byte) colIndex);
Now I am trying to piece these extracted arrays back together to make it readable. I will need to do some manipulation on some of the columns and then write to a text file after consolidating. The only problem is that I have no idea how to do this correctly. I have tried the following methods but continue to get a null reference exception:
// Get Row Count of dataArray
int rowCount = dataArray.GetLength(0);
// Create List to store extracted arrays
List<object[]> extractedDataList = new List<object[]>();
// Loop through target columns and extract the column as an array
for (byte colIndex = 1; colIndex <= targetColumns.Length + 1; colIndex++)
{
object[] array = ExtractColumn(dataArray, (byte) colIndex);
extractedDataList.Add(array);
}
// Create jagged array
object[][] extractedDataArray = new object[rowCount][] ;
for(int i = 0; i < extractedDataArray.GetLength(0); i++)
{
List<object> row = new List<object>();
for (int j = 0; j < extractedDataList.Count; j++)
{
row.Add(extractedDataList[j][i].ToString());
//extractedDataArray[i][j] = extractedDataList[j][i].ToString(); <-- null reference
}
extractedDataArray[i] = row.ToArray();
}
I'm at a loss of what else to try to put these column arrays back in a form that I can easily work with. Any and all tips/recommendations would be greatly appreciated.
Whenever you get confused like this, break the problem down into small pieces, and use meaningful names.
Let's say you have an array of columns, each of which has one element per row. That might be declared like this:
object[][] columns;
First, let's get the row and column counts:
var columnCount = columns.Length;
var rowCount = columns[0].Length;
Now write a small local function to accept a row and column index and return the right cell. In case not all of your columns have the same number of rows, you can include a boundary check and just return null if a cell isn't there.
object Getter(int row, int col)
{
bool outOfBounds = (row >= columns[col].Length);
return outOfBounds ? null : columns[col][row];
}
Now all we have to do is iterate over the rows to create the inner arrays:
object[][] target = new object[rowCount][]
for (int row = 0; row < rowCount; row++)
{
target[row] = new object[columnCount];
}
And add in the code that uses the getter to populate the cells:
object[][] target = new object[rowCount][];
for (int row = 0; row < rowCount; row++)
{
target[row] = new object[columnCount];
for (int col = 0; col < columnCount; col++)
{
var cellValue = Getter(row, col);
target[row][columnCount] = cellValue;
}
}
All together, it is simple to read:
var columnCount = columns.Length;
var rowCount = columns[0].Length;
object Getter(int row, int col)
{
bool outOfBounds = (row >= columns[col].Length);
return outOfBounds ? null : columns[col][row];
}
object[][] target = new object[rowCount][];
for (int row = 0; row < rowCount; row++)
{
target[row] = new object[columnCount];
for (int col = 0; col < columnCount; col++)
{
var cellValue = Getter(row, col);
target[row][columnCount] = cellValue;
}
}

cannot apply indexing with [] to an express of type 'method group, (how to print array)

i have array that call nums, it contain int var.
the array is 2d -
int[,] nums = new int[lines, row];
i need to print each line in the array in other line.
when i try to print to array like this:
for (int i = 0; i < lines; i++)
for (int j = 0; j < 46; j++)
Console.Write(nums[i,j]);
** when i using the above syntax i dont get an error in visual studio, but when i run the program, i got error in this line - Console.Write(nums[i,j]);.
error - system.IndeOutOfRangeException.
i got the error , i try to change the syntax to this:
for (int i = 0; i < lines; i++)
for (int j = 0; j < 46; j++)
Console.Write(nums[i][j]);
the error: "wrong number of indices inside []; expected 2"
and:
for (int i = 0; i < lines; i++)
for (int j = 0; j < 46; j++)
Console.Write(nums[i][j].tostring());
update
i am so stupid... i write 46(number in my program) instead of 6(numbers in each row) thats whey is was out of range.
ty for all, and i am sry to open a question with such bad problem...
TY!
If lines and row are positive integer values, say, int lines = 5; int row = 7; you can print out your table like this:
int[,] nums = new int[lines, row]; // <- Multidimensional (2 in this case) array, not an array of array which is nums[][]
//TODO: fill nums with values, otherwise nums will be all zeros
for (int i = 0; i < lines; i++) {
Console.WriteLine(); // <- let's start each array's line with a new line
for (int j = 0; j < row; j++) { // <- What the magic number "46" is? "row" should be here...
Console.Write(nums[i, j]); // <- nums[i, j].ToString() doesn't spoil the output
if (j > 0) // <- let's separate values by spaces "1 2 3 4" instead of "1234"
Console.Write(" ");
}
}
You are dealing with 2 different types of arrays
int[,] nums = new int[lines, row];
is a Multi-Dimensional Array. Elements of the array can be accessed using nums[x,y].
When you use nums[x][y] you are dealing with an array of arrays.
You cannot use array of arrays syntax with a multi-dimensional array.
You might try What are the differences between Multidimensional array and Array of Arrays in C#? for details.

C# multi-dimension array sort based on user input

How can I sort a 2D array in C#
I have looked at other answers to this question but they don't do exactly what I need.
The array is variable height * 5 across
The array holds strings
I need the array sorted based on either column, for example sort in alphabetical the third column, however all other columns must be updated.
Does anyone know of a quick and easy solution?
My code is a mess, here is a shortened version:
string[,] tmp = new string[2, 3];//this is filled with strings
string y = Console.ReadLine();
int x = Convert.ToInt32(y);
// sort tmp based on x column
How do I sort a two-dimensional array in C#? contains a possible solution to this by reading your data into a datatable and then using the object's methods to sort:
// assumes stringdata[row, col] is your 2D string array
DataTable dt = new DataTable();
// assumes first row contains column names:
for (int col = 0; col < stringdata.GetLength(1); col++)
{
dt.Columns.Add(stringdata[0, col]);
}
// load data from string array to data table:
for (rowindex = 1; rowindex < stringdata.GetLength(0); rowindex++)
{
DataRow row = dt.NewRow();
for (int col = 0; col < stringdata.GetLength(1); col++)
{
row[col] = stringdata[rowindex, col];
}
dt.Rows.Add(row);
}
// sort by third column:
DataRow[] sortedrows = dt.Select("", "3");
// sort by column name, descending:
sortedrows = dt.Select("", "COLUMN3 DESC");
So first we'll want to convert the multi-dimensional array into a sequence of single-dimensional arrays representing the rows, so that each row can be manipulated as a unit:
public static IEnumerable<T[]> GetRows<T>(T[,] array)
{
for (int i = 0; i < array.GetLength(0); i++)
{
T[] row = new T[array.GetLength(1)];
for (int j = 0; j < row.Length; j++)
{
row[j] = array[i, j];
}
yield return row;
}
}
Then we'll also need a method that does the reverse to get a multi-dimensional array back when we're done:
public static T[,] ToMultiDimensionalArray<T>(T[][] rows)
{
T[,] output = new T[rows.Length, rows[0].Length];
for (int i = 0; i < rows.Length; i++)
for (int j = 0; j < rows[0].Length; j++)
{
output[i, j] = rows[i][j];
}
return output;
}
Now we just need to sort a sequence of arrays, and Linq makes this quite easy:
tmp = ToMultiDimensionalArray(GetRows(tmp)
.OrderBy(row => row[2]).ToArray());

Delete row of 2D string array in C#

I am making a program that stores data in a 2D array. I would like to be able to delete rows from this array. I cannot figure out why this code doesn't work:
for (int n = index; n < a.GetUpperBound(1); ++n)
{
for (int i = 0; i < a.GetUpperBound(0); ++i)
{
a[i, n] = a[i, n + 1];
}
}
Could someone please help me out? I would like it to delete a single row and shuffle all the rows below it up one place. Thankyou!
you need to create a new array if you want to delete an item
try something like this
var arrayUpdated = new string[a.GetUpperBound(1)][a.GetUpperBound(0)-1];
for (int n = index; n < a.GetUpperBound(1); n++)
{
for (int i = 0; i < a.GetUpperBound(0); i++)
{
arrayUpdated [i, n] = a[i, 1];
}
}
The nested for loop method here works well: https://stackoverflow.com/a/8000574
Here's a method that converts the outer loop of the [,] array method above to use linq. Using linq here is only recommended if you are also doing other things with linq during the traversal.
public T[,] RemoveRow<T>(T[,] array2d, int rowToRemove)
{
var resultAsList = Enumerable
.Range(0, array2d.GetLength(0)) // select all the rows available
.Where(i => i != rowToRemove) // except for the one we don't want
.Select(i => // select the results as a string[]
{
T[] row = new T[array2d.GetLength(1)];
for (int column = 0; column < array2d.GetLength(1); column++)
{
row[column] = array2d[i, column];
}
return row;
}).ToList();
// convert List<string[]> to string[,].
return CreateRectangularArray(resultAsList); // CreateRectangularArray() can be copied from https://stackoverflow.com/a/9775057
}
used Enumerable.Range to iterate all rows as done in https://stackoverflow.com/a/18673845
Shouldn't ++i be i++? ++i increments before matrix operation is performed(ie pre-increment)

Categories