如何有效地为大型数组分配公共初始值? 例如,如果我有一个100乘100乘100的整数数组,其中所有初始值都应为零。
在matlab中,我只想写:
array = zeros(100,100,100);
如果没有C#循环,我怎么能这样做?
答案 0 :(得分: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的ones()函数。 要实现零(),可以使用以下代码:
Array.Clear(cube, 0, A*B*C);
答案 1 :(得分: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;
}
}
}
}
答案 2 :(得分:1)
您可以像这样使用Enumerable.Repeat
:
int[] zeros1Dim = Enumerable.Repeat(0, 100).ToArray();
int[][] zeros2Dim = Enumerable.Repeat(zeros1Dim, 100).ToArray();
int[][][] array = Enumerable.Repeat(zeros2Dim, 100).ToArray();
答案 3 :(得分: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);
答案 4 :(得分:-1)
在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 method,正如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);