如何有效地将公共初始值分配给大型数组?例如,如果我有一个 100 x 100 x 100 整数数组,其中所有初始值都应该为零。
在matlab中我会简单地写:
array = zeros(100,100,100);
如果没有 C# 中的循环,我怎么能做到这一点?
如何有效地将公共初始值分配给大型数组?例如,如果我有一个 100 x 100 x 100 整数数组,其中所有初始值都应该为零。
在matlab中我会简单地写:
array = zeros(100,100,100);
如果没有 C# 中的循环,我怎么能做到这一点?
只是为了争论(我个人认为这不是一种好的编程风格),但它可以在 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);
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;
}
}
}
}
您可以Enumerable.Repeat
像这样使用它:
int[] zeros1Dim = Enumerable.Repeat(0, 100).ToArray();
int[][] zeros2Dim = Enumerable.Repeat(zeros1Dim, 100).ToArray();
int[][][] array = Enumerable.Repeat(zeros2Dim, 100).ToArray();
我不知道在 C# 中初始化数组的惯用、非循环方式,根据这里的答案,其他人似乎也不知道。不安全的内存复制可能需要更少的代码行,尽管它确实混淆了您正在做的事情的含义:它强调机制(将此值移动到此内存地址)而不是语义(使整个多维数组等于相同的值。)
鉴于此,我的建议是咬紧牙关,使用一个循环,然后用一个命名愉快的方法将其抽象出来:
public static T[,,] FillArrayWithValue<T>(this T[,,] array, T value)
{
// Loops go here
}
将其粘贴在某个静态实用程序类中,然后您的调用站点变为:
int[,,] myArray = new int[4, 5, 6];
myArray.FillArrayWithValue(value);
在 C 编程领域,通常使用诸如memcpy或CopyMemory之类的 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);