So I have this object in C#, which will contain ints and bools (doubles and logicals)
object[,] matrixData = new object[iDimensions[0], iDimensions[1]];
and I pass it to matlab:
matlab.PutWorkspaceData("matrixData", "base", matrixData);
Matlab sees this as a cell array of arrays. Which is inconvenient since I now cannot use these values for anything. I guess I need to convert these into a numerical array - although in truth I'd be happier to retain the strong typing and just lose the array within each cell.
So, for example:
temp = cell(1,4)
temp{1,1} = [0.5]
temp{1,2} = [1==1]
temp{1,3} = [7424.356]
temp{1,4} = [31]
and I want to have:
output = [0.5, 1==1, 7424.356, 31]
So my current implementation is pretty crass:
cellfun(#decellify,CashFlowBasisMatrixData);
where
function decellified = decellify(object)
if isa(object,'logical')
decellified = +object;
end
if isa(object,'float')
decellified = object;
end
if isa(object,'char')
decellified = -2;
end
end
Is there a better way? If I do the conversion to doubles in C# how do I 'un-array' each element?
Thanks,
Nt
Related
I need to call a C++ routine with a KeyValuePair parameter. I have an example in C#;
KeyValuePair[] dataArray =
new KeyValuePair[]{
new KeyValuePair() { key = 1234, value = "Atlanta" },
new KeyValuePair() { key = 70, value = "Atlanta" },
new KeyValuePair() { key = 2320, value = "999999999" }};
This seems to translates to;
Dim dataArray As KeyValuePair() = New KeyValuePair() {New KeyValuePair() With {
.key = 1234,
.value = "Atlanta"
}, New KeyValuePair() With {
.key = 70,
.value = "Atlanta"
}}
in VB.
I have two questions;
What is this structure called? I would call it an array of KeyValuePairs. So I know how to reference the structure when I search.
How does one add additional values dynamically?
EDIT:
More specifically I have a function whose purpose is to build the same type of structure statically built in the C# code above by reading values from a database. I had originally written the code assuming the "list of" key value pairs is what I needed. Here is that code;
Private Function buildDataRecord(ByRef objRecord As OracleDataReader) As List(Of KeyValuePair(Of Integer, String))
Dim i As Integer = 0
Dim lstFieldData As List(Of KeyValuePair(Of Integer, String)) = New List(Of KeyValuePair(Of Integer, String))
Dim strFieldName As String
On Error GoTo buildDataRecordError
For i = 0 To objRecord.FieldCount - 1
strFieldName = objRecord.GetName(i)
If strFieldName.Substring(0, 3) = "IN_" _
Then
lstFieldData.Add(New KeyValuePair(Of Integer, String)(CInt(strFieldName.Substring(3)), Trim(objRecord(i).ToString)))
End If
Next
Return lstFieldData
buildDataRecordError:
Err.Raise(Err.Number,
"buildDataRecord",
Err.Description,
Err.HelpFile,
Err.HelpContext)
When calling C++ I get the error;
Cannot marshal 'parameter #4': Generic types cannot be marshaled.
My assumption is I do not have the correct data type.
What is this structure called?
An Array of KeyValuePair. Arrays are CLR types shared by all languages.
How does one add additional values dynamically?
An array is a fixed-size data structure, so you don't just add additional items like you can with a List. But you can resize an array. VB has ReDim, or you can use the generic Array.Resize method that could also be used from C#.
C++ code rely a lot about how your memory is organized for your type.
C# generic type are just describing what the type should contains but nothing about memory organisation. Memory organisation is decided by JIT when it knows the true types of T1 and T2. JIT will probably align Item1 and Item2 on multiple of 8 in memory. It can store Item2 before Item1 (for example if item1 is byte and item2 an int). And in Debug the organisation can be different than in Release. This is why generic are not supported.
You have to define your own struct type for all not generic type versions of KeyValuePair you want to use. And I recommend you to use attribute like this to make thing explicit. Example if you want to handle KeyValuePair<byte, int>
[StructLayout(LayoutKind.Explicit)]
public struct KeyValuePairOfIntAndByte // For KeyValuePair<int, byte>
{
// note how fields are inversed in memory...
// this is the kind of optimisation JIT usually does behind your back
[FieldOffset(0)] public int Item2;
[FieldOffset(sizeof(int))] public byte Item1;
}
So make conversion of your KeyValuePair<int, byte> instance to an array of this struct and that should be ok.
Note that you will have to pin memory while your C++ code is using this C# array too... otherwise Garbage Collector can decide at any time to move your array elsewhere in memory (while your C++ code is using it...)
I strongly recommend you to read this: https://learn.microsoft.com/en-us/dotnet/framework/interop/copying-and-pinning if you want to continue on this way
For information Swig is a library that generate C# code for you that wrap C++ library so you can use C++ library as if it was written in C# (a lot simpler then...) without thinking too much about all the work you have to do. If you look at the generated code you will understand how complex it can be to do interop code right.
I use Python.Net for C# interaction with Python libraries. I solve the problem of text classification. I use FastText to index and get the vector, as well as Sklearn to train the classifier (Knn).During the implementation, I encountered a lot of problems, but all were solved, with the exception of one.
After receiving the vectors of the texts on which I train Knn, I save them to a separate text file and then, if necessary, use it.
string loadKnowVec = File.ReadAllText("vectorKnowClass.txt", Encoding.Default);
string[] splitKnowVec = loadKnowVec.Split('\r');
splitKnowVec = splitKnowVec.Where(x => x != "").ToArray();
for()
{
keyValues_vector.Add(float.Parse(splitKnowVec[i], NumberFormatInfo.InvariantInfo), 1);
}
dynamic X_vec = np.array(keyValues_vector.Keys.ToArray()).reshape(-1, 1);
dynamic y_tag = np.array(keyValues_vector.Values.ToArray());
dynamic neigh = KNN(n_neighbors: 3);
dynamic KnnFit = neigh.fit(X_vec, y_tag);
string predict = neigh.predict("0.00889");
MessageBox.Show("Скорее всего это: "+predict);
During the training of the classifier, I encountered such a problem that from c# to python, it is not values with the float type, but the value of System.Single[].
Python.Runtime.PythonException: "TypeError : float() argument must be a string or a number,
not 'Single[]'
The stored value, at this point, of dynamic X_vec is "System.Single[]".(I think that's exactly the problem)
2.At first I tried to manually set the values of X_vec, but the error and its values were the same.
The first idea was to change the array type using the numpy library, but it didn't help, it also gave out "".
dynamic Xx = np.array(X_vec, dtype: "float");
dynamic yY = np.array(y_tag, dtype: "int");
Next, it was tried to create an empty array in advance and load specific values into it before changing the data type, but this also did not work.
Perhaps I do not understand the principle of the formation and interaction of the MSVS19 IDE and the python interpreter.
I solved this issue for a couple of days and each time I thought it was worth reading the documentation on python.net .
As a result, I found a solution and it turned out to be quite banal, it is necessary to represent X_vec not as a float[] , but as a List<float>
List<float> vectors = keyValues_vector.Keys.ToList();
List<int> classTag = keyValues_vector.Values.ToList();
dynamic a = np.array(vectors);
dynamic X_vec = a.reshape(-1, 1);
dynamic y_tag = np.array(classTag);
I want to create an array of references to my arrays. The reason for this is because i want to optimise my fast Fourier transform algorithm to be branchless - or rather, less branchy.
The idea behind it is i have two arrays:
Array1 and Array2
I need to ping pong between the two in a for loop so i want to store the reference to the arrays like this:
[0] = Array1Ref
[1] = Array2Ref
[2] = Array1Ref
. . .
Is it possible to do this in C#? If so how would you define such an array - would i need to use unsafe ?
If you just want to access a different array in each iteration of the for loop without using a conditional, you can keep swapping two variables and use one of them.
var arrayRef = Array1;
var theOtherArrayRef = Array2;
for (...) {
// use arrayRef in places where you would have accessed the array of array references
...
// C# 7 tuple syntax
(arrayRef, theOtherArrayRef) = (theOtherArrayRef, arrayRef);
// pre-C# 7:
/*
var temp = arrayRef;
arrayRef = theOtherArrayRef;
theOtherArrayRef = arrayRef;
*/
}
I am trying to check if two arrays of equal size contain the same integers at the same indexes. If some element are not equal I want to return true, and otherwise return false.
public bool multipleSolutions(int[,] grid)
{
int[,] front = new int[9, 9];
front = grid;
int[,] back = new int[9, 9];
back = grid;
front = solve(front);
back = solveBackwards(back);
for (int r = 0; r < 9; r++)
{
for (int c = 0; c < 9; c++)
{
if (back[r, c] != front[r, c])
{
return true;
}
}
}
return false;
}
When tested separately, solve and solveBackwards give two different arrays, but when I try multipleSolutions it still gives me false (since they are two different arrays, I want it to return true).
Since the test logic is correct the most likely cause to this error is that the implementation of solve and solvebackwards changes the array passed in and returns the same array.
For both the call to solve and to solveBackwards the array identified by the parameter grid is passed in. So if solve changes the passed-in array then the input for solveBackwards has been changed accoring to the first run. Which might affect solveBackwards. The result wouldn't differ though because under th above assumption when solveBackwards is done. both front and back would then be the result of the solveBackwards
assumptions
solve and solveBackwards alters the array passed in
the return value of solve and solveBacrwards are the array passed in
EDIT
Seeing the the assumptions are correct you could insert this as the first line in both solve and solveBackwards
var temp = new int[9,9]
Array.Copy(grid, 0, temp, 0, grid.Length);
and then use temp through the implementation of solve and solvebackwards.
Alternatively you could do the same for front and back before passing them in as an argument
however you should then change the return type of the two methods. Specifying a return type is indicative of returning a different object and not mutating the argument. This is also why I'd prefer the first option (copying the array inside the method)
However even better in my opinion would be to iterate the input array and constructing an inemurable with the result
The problem is that you put the grid array in both the front and back variables. When you assing an array to an array variable, it doesn't copy the data from one array to another, it copies the reference to the array object. All your references will end up pointing to the same array object.
To copy the data from one array to another you can use the Copy method:
int[,] front = new int[9, 9];
Array.Copy(grid, front, grid.Length);
int[,] back = new int[9, 9];
Array.Copy(grid, back, grid.Length);
Now you have two new array objects that contain the data from the original grid.
In C# you can do this:
poules = new int[aantal, aantal, 2];
I couldn't find a way in PHP to do this. All I can find is a two dimensional array.
The example you presented is creating a 3D array, and getting it by a method (which is a bit slower, since a method is used). PHP uses jagged arrays.
An array in PHP is created using the array function.
To match your example: (for fixed array length)
$myArr = new SplFixedArray($aantal);
for ($i = 0; $i < $aantal; $i++) {
$myArr[$i] = new SplFixedArray($aantal);
for ($j = 0; $j < $aantal; $j++) {
$myArr[$i][$j] = new SplFixedArray(2);
}
}
SplFixedArray is used to define an array with a fixed size.
As claimed in comments, you will rarely see a PHP code as the above.
you can access the array cells like this:
$val = $myArr[$x][$y][$z];
Here is a reference: SplFixedArray
I'm not a C# person, so take this with a grain of salt. After perusing the documentation though, new int[aantal, aantal, 2] seem to be the syntax to declare multi-dimensional int arrays, in this case a 3-dimensional array.
PHP doesn't have multi-dimensional arrays. It only has arrays, and you can have arrays of arrays. I guess this is called a "jagged array" in C#. PHP arrays are also not typed, there's no equivalent to int[].
You can simply declare/access several dimensions at once though:
$arr = array();
$arr[1][2][3] = 'foo';
PHP will create the intermediate arrays as needed. The array is jagged though, there's no $arr[0][2][3] after the above code executed.
If you need to pre-allocate all dimensions beforehand, you will have to recursively loop. This is not really something done very often in PHP though, you should adapt your practices to work with jagged arrays to get things done.
This would be a php array:
$poules = array('aantal', 'anntal', '2');
In case aantal is a variable, just the same without quotes:
$poules = array($aantal, $anntal, '2');
In PHP you don't need to specify the variable type. Although you can use it to validate or filter inputs.
You can read more about PHP arrays in the official documentation:
http://uk3.php.net/manual/en/language.types.array.php
$poules = array('aantal', 'aantal', 2);
Or are aanta1 arrays too? Because in php you can do:
$myArray = array("some data", array("more data", "in a other array"), array("key1" => "even with keys"));