2

如何有效地将公共初始值分配给大型数组?例如,如果我有一个 100 x 100 x 100 整数数组,其中所有初始值都应该为零。

在matlab中我会简单地写:

array = zeros(100,100,100);

如果没有 C# 中的循环,我怎么能做到这一点?

4

5 回答 5

2

只是为了争论(我个人认为这不是一种好的编程风格),但它可以在 C# 中一行完成,技术上没有循环但使用 LINQ

int[,,] cube = new int[A, B, C];
Enumerable.Range(0, A*B*C).Select(i => cube[i/(B*C), i%(B*C)/C, i%C] = 1).Count();

这里的 Count() 只需要使序列被枚举,它的结果被忽略。这是为了实现 MATLAB 的 one() 函数。要实现 zeros(),可以使用以下命令:

Array.Clear(cube, 0, A*B*C);
于 2012-09-23T02:35:44.497 回答
1
public void SetAllValues(int[,,] data, int value) {
    for (int x = 0; x < data.GetLength(0); x++) {
        for (int y = 0; y < data.GetLength(1); y++) {
            for (int z = 0; z < data.GetLength(2); z++) {
                data[x, y, z] = value;
            }
        }
    }
}
于 2012-09-22T19:46:02.597 回答
1

您可以Enumerable.Repeat像这样使用它:

int[] zeros1Dim = Enumerable.Repeat(0, 100).ToArray();
int[][] zeros2Dim = Enumerable.Repeat(zeros1Dim, 100).ToArray();
int[][][] array = Enumerable.Repeat(zeros2Dim, 100).ToArray();
于 2012-09-22T19:55:56.747 回答
0

我不知道在 C# 中初始化数组的惯用、非循环方式,根据这里的答案,其他人似乎也不知道。不安全的内存复制可能需要更少的代码行,尽管它确实混淆了您正在做的事情的含义:它强调机制(将此值移动到此内存地址)而不是语义(使整个多维数组等于相同的值。)

鉴于此,我的建议是咬紧牙关,使用一个循环,然后用一个命名愉快的方法将其抽象出来

public static T[,,] FillArrayWithValue<T>(this T[,,] array, T value)
{
    // Loops go here
}

将其粘贴在某个静态实用程序类中,然后您的调用站点变为:

int[,,] myArray = new int[4, 5, 6];
myArray.FillArrayWithValue(value);
于 2012-09-23T01:24:48.643 回答
-1

在 C 编程领域,通常使用诸如memcpyCopyMemory之类的 OS 函数来有效地将内存从一个地方移动到另一个地方。这比使用循环要好得多,因为操作系统将使用专用硬件 ( DMA ) 来执行操作。

我不确定这是否对您的简单案例有用,但如果您愿意,可以从某些 DLL 导入这些函数。

[DllImport("kernel32.dll")]
static extern void CopyMemory(IntPtr destination, IntPtr source, uint length);

static void Main(string[] args)
{
    byte[] a = new byte[10]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    byte[] b = new byte[10];

    IntPtr pa = Marshal.UnsafeAddrOfPinnedArrayElement(a, 0);
    IntPtr pb = Marshal.UnsafeAddrOfPinnedArrayElement(b, 0);

    CopyMemory(pb, pa, 10);
}

CopyMemory函数仅适用于连续的内存块,因此请注意如何调用它。

重要编辑:

如果您查看下面的注释,您会注意到上面显示的这段代码远非“可用”,因为它可能会在您不知道的情况下破坏您的应用程序内存。更好的方法是使用Buffer.BlockCopy 方法,正如codesparkle 所建议的那样,它可能在内部做同样的事情,但以安全的方式:

byte[] a = new byte[10]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
byte[] b = new byte[10];
Buffer.BlockCopy(a, 0, b, 0, 10);
于 2012-09-22T20:47:03.570 回答