我正在使用NumSharp并且对它有点陌生。我想设置多个数据值,主要关注两个功能:
NDArray.SetValue(object value, param int[] indices)
NDArray.SetData(object value, param int[] indices)
第一个SetValue
期望单个值元素的完整索引,例如,如果您拥有np.zeros(3,3)
它期望完整索引,并且如果缺少索引,它将使用0
它的位置。
例如:
var arr = np.zeros(3,3);
arr.SetValue(10.0, 0);
arr.SetValue(10.0, 0, 0);
两条线是等价的。
另一方面,SetData
将根据索引修改整个子数组,如果给出完整索引,它的工作方式类似于SetValue
. 例如:
arr.SetData(10.0, 0); // sets all arr[0] values to 10
arr.SetData(10.0, 0, 1); // sets arr[0][1] to 10
现在,对于我的用例,我想重新定义一个接受多个值并将每个值视为子数组索引的函数。
arr.SetMultiData(10.0, 0, 1); /// sets arr[0] and arr[10] values to 10
自然,我选择了一种扩展方法:
public static class Extensions
{
public static void SetMultiData(this NDArray arr, object value, int[] indices)
{
foreach (var i in indices)
arr.SetData(value, i);
}
}
但这就是完全失去我的地方。此代码不使用扩展方法,有效:
static void Main(string[] args)
{
NDArray arr = np.zeros(3, 3);
int[] indices = new int[] { 0, 1 };
double value = 10;
foreach (var i in indices)
arr.SetData(value, i);
Console.WriteLine(arr.ToString());
}
输出:
[[10, 10, 10],[10, 10, 10],[0, 0, 0]]
此代码不会:
static void Main(string[] args)
{
NDArray arr = np.zeros(3, 3);
int[] indices = new int[] { 0, 1 };
double value = 10;
arr.SetMultiData(value, indices);
Console.WriteLine(arr.ToString());
}
输出:
[[10, 0, 0],[0, 0, 0],[0, 0, 0]]
这并不总是会打印,在大多数情况下它只是无法打印,我相信底层arr
结构已相应损坏,当我多次运行它时会导致未定义的行为。
现在,最后一点。当我将Extension
方法更改为 acceptdouble
而不是 时object
,它可以完美运行。但是我需要扩展方法来处理多种类型,因为它只是SetData
. 鉴于此,我还尝试将方法更改为通用:
public static class Extensions
{
public static void SetMultiData<T>(this NDArray arr, object value, int[] indices)
{
T val = (T)value;
foreach (var i in indices)
arr.SetData(val, i);
}
}
当这不起作用并产生相同的输出时,我感到震惊。基本上,我进行了从对象到类型的显式转换。我这样调用函数:我使用调试器并比较了与它一起工作的代码,类型与传递给给定andarr.SetMultiData<double>(value, indicies);
的类型完全相同,但一个有效,一个无效。arr.SetValue
i = int
val = double
是什么导致了这种行为?为什么当我明确地将它设置为double
使用泛型/object
类型都失败时它会起作用?
作为参考,这里是SetData
实现。这是开源的。