c# - 在c#中填充多维数组而不用单值循环

标签 c# arrays loops multidimensional-array

在 C# 中有没有一种方法可以在不使用循环的情况下将多维数组的每个值设置为特定值?我找到了 Array.Fill但它似乎只适用于一维数组。

基本上我要找的是这样的东西:

double[,,,] arrayToFill = new double[7,8,9,10];
Array.FillWhole(arrayToFill, 1.2345);

当然可以只使用嵌套循环,但在处理高维数组时不是很烦人吗?

最佳答案

(请参阅此答案中的最后一个代码示例以获得最佳解决方案。)

您实际上可以使用 Span<T>这样做,但它看起来很繁琐!

double[,,,] arrayToFill = new double[7, 8, 9, 10];

var data = MemoryMarshal.CreateSpan(
    ref Unsafe.As<byte, double>(ref MemoryMarshal.GetArrayDataReference(arrayToFill)),
    arrayToFill.Length);

data.Fill(1.2345);

foreach (var value in arrayToFill)
{
    Console.WriteLine(value);  // All values are 1.2345
}

你可以写一个方法来封装这个:

public static void FillArray<T>(Array array, T value)
{
    var data = MemoryMarshal.CreateSpan(
        ref Unsafe.As<byte, T>(ref MemoryMarshal.GetArrayDataReference(array)),
        array.Length);

    data.Fill(value);
}

然后调用站点变得更具可读性:

double[,,,] arrayToFill = new double[7, 8, 9, 10];

FillArray(arrayToFill, 1.2345);

foreach (var value in arrayToFill)
{
    Console.WriteLine(value);  // All values are 1.2345
}

如果你想要更花哨,你可以将它封装在一个扩展方法中:

public static class ArrayExt
{
    public static void Fill<T>(this Array array, T value)
    {
        var data = MemoryMarshal.CreateSpan(
            ref Unsafe.As<byte, T>(ref MemoryMarshal.GetArrayDataReference(array)),
            array.Length);

        data.Fill(value);
    }
}

然后你可以这样调用它:

double[,,,] arrayToFill = new double[7, 8, 9, 10];

arrayToFill.Fill(1.2345);

foreach (var value in arrayToFill)
{
    Console.WriteLine(value);  // All values are 1.2345
}

重要!您必须确保使用正确的类型来填充数组。如果您指定了错误的类型,它将用垃圾填充数组,例如:

arrayToFill.Fill(1);

真的会把事情搞砸。

在此示例中,您需要执行 arrayToFill.Fill<double>(1);指定正确的类型,否则它会推断出填充数组的错误类型。

根据来自/u/charlieface 的评论,您可以通过为每个数组维度添加强类型重载来规避此问题,因此:

这可能是最好的方法:

public static class ArrayExt
{
    public static void Fill<T>(this T[,]    array, T value) => fill(array, value);
    public static void Fill<T>(this T[,,]   array, T value) => fill(array, value);
    public static void Fill<T>(this T[,,,]  array, T value) => fill(array, value);
    public static void Fill<T>(this T[,,,,] array, T value) => fill(array, value);

    static void fill<T>(Array array, T value)
    {
        var data = MemoryMarshal.CreateSpan(
            ref Unsafe.As<byte, T>(ref MemoryMarshal.GetArrayDataReference(array)),
            array.Length);

        data.Fill(value);
    }

    // ...etc etc. But does anyone really need more than a 5D array? ;)
}

然后arrayToFill.Fill(1);将正常工作。


另见 this post from /u/charlieface

关于c# - 在c#中填充多维数组而不用单值循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73401522/

相关文章:

c# - 每秒 SQL 查询

c# - 具有不同身份验证 header 的 HttpClient 单个实例

c# - 虚拟主机.exe。为什么需要这个?

c# - 检索自定义属性参数值?

ios - 如何在 Swift 中使用按钮单击功能将 [PHAsset] 转换为 PHAsset

Python:如何在无限循环运行时从控制台获取输入?

javascript - 将事件处理程序添加到数组

c - 数组地址在 C 中不正确递增

java - 如何 append 变量 ID - AndroidX

c++ - Arduino - 通过按钮停止循环