I have the following code below but haven't figured out how to implement the
var results =
section so that result[c] = valuesArray;
works properly?
var result = Array.CreateInstance(typeof(Array), dt.Columns.Count);
foreach (int c in Enumerable.Range(0, dt.Columns.Count))
{
// Create a list to hold values of the required type for the column
var valuesArray = Array.CreateInstance(typeof(float), dt.Rows.Count);
// Get the data to be written to the parquet stream
for (int r = 0; r < dt.Rows.Count; r )
{
DataRow row = dt.Rows[r];
valuesArray.SetValue(row[c], r);
}
result[c] = valuesArray;
The error is:
Error: CS0021 = Cannot apply indexing with [] to an expression of type 'Array'
How do I instiate the Array
so it works?
CodePudding user response:
Just as you set a value to valuesArray
with the SetValue()
method, you can do the same for result
:
result.SetValue(valuesArray, c);
If you need to retrieve the value during iteration, you can use result.GetValue(c)
:
foreach (int c in result)
{
var retrievedResult = result.GetValue(c);
}
CodePudding user response:
The Nice approach that I've tried and works correctly is:
var result = (dynamic)Array.CreateInstance(typeof(Array), columnLength);
The sample code is:
int columnLength = 8;
var result = (dynamic)Array.CreateInstance(typeof(Array), columnLength);
foreach (int c in Enumerable.Range(0, columnLength)) {
// Create a list to hold values of the required type for the column
var valuesArray = Array.CreateInstance(typeof(float),columnLength);
// Get the data to be written to the parquet stream
for (int r = 0; r < columnLength; r ) {
valuesArray.SetValue(r, r);
}
result[c] = valuesArray;
}
foreach (var arr in result)
foreach (var value in arr)
Console.Write($"{value}\t");
Console.ReadLine();
The Output is:
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6
7 0 1 2 3 4 5 6 7 0 1 2 3 4
5 6 7 0 1 2 3 4 5 6 7 0 1 2
3 4 5 6 7 0 1 2 3 4 5 6 7 0
1 2 3 4 5 6 7
CodePudding user response:
It looks like result.SetValue(valuesArray, c)
will work.
You can also get the value with
result.GetValue(c);
So if you need to iterate through result
you can write a foreach
similar to the one you already wrote.
foreach (int c in Enumerable.Range(0, dt.Columns.Count))
{
var x = result.GetValue(c);
}
CodePudding user response:
You can utilize generics for this. The only reflection you need is to execute the inner function once per column.
- The initial array of arrays can be done without
Array.CreateInstance
var method = this.GetType().GetMethod("GetArray");
var result = new Array[dt.Columns.Count];
for (int c = 0; c < dt.Columns.Count; c )
{
var generic = method.MakeGenericMethod(dt.Columns[c].DataType);
result[c] = (Array)generic.Invoke(null, new[]{dt.Rows, c});
}
public static Array GetArray<T>(DataRowCollection rows, int c)
{
var valuesArray = new T[rows.Count];
for (int r = 0; r < rows.Count; r )
{
DataRow row = rows[r];
valuesArray[r] = (T)row[c];
}
return valuesArray;
}
In high performance scenarios, you could even cache a delegate to the generic function
static MethodInfo method = this.GetType().GetMethod("GetArray");
static Dictionary<Type, Func<DataRowCollection, int, Array>> funcs = new();
var result = new Array[dt.Columns.Count];
for (int c = 0; c < dt.Columns.Count; c )
{
if(!funcs.TryGetValue(dt.Columns[c].DataType, out var func)
{
func = funcs[dt.Columns[c].DataType] =
(Func<DataRowCollection, int, Array>) method.MakeGenericMethod(dt.Columns[c].DataType)
.CreateDelegate(typeof(Func<DataRowCollection, int, Array>));
}
result[c] = func(dt.Rows, c);
}