C#将一维数组转换为二维数组

10

我发现自己通过以下方式将1D字节和单个数组转换为2D数组。 我怀疑它可能与其他方法一样快,但也许有一种更干净简单的模式?(Linq?)

    private static byte[,] byte2D(byte[] input, int height, int width)
    {
        byte[,] output = new byte[height, width];
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                output[i, j] = input[i * width + j];
            }
        }
        return output;
    }

    private static Single[,] single2D(byte[] input, int height, int width)
    {
        Single[,] output = new Single[height, width];
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                output[i, j] = (Single)input[i * width + j];
            }
        }
        return output;
    }

你的第二个方法,input 参数的类型应该是 byte[] 吗? - ryanyuyu
你能提供其中一个函数的样例输入/输出吗? - Abe Miessler
4个回答

13
这并不能帮助方法内的代码变得更加清晰,但我注意到您有两个基本相同的方法,它们仅在类型上有所不同。建议使用泛型

这将允许您仅定义一次方法。使用where关键字,甚至可以限制您的方法可用的数据类型种类。

private static T[,] Make2DArray<T>(T[] input, int height, int width)
{
    T[,] output = new T[height, width];
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            output[i, j] = input[i * width + j];
        }
    }
    return output;
}

你可以这样调用该方法。
int[] a;  //or any other array.
var twoDArray = Make2DArray(a, height, width);

Buffer.BlockCopy() 更快更简洁。自 Framework 1.1 以来就存在。 - dynamichael
@dynamichael 只有在你的类型实际上具有常量大小(以字节为单位)时才有效.. 对于 string 等不起作用。 - derHugo

5

Buffer.BlockCopy(input, 0, output, 0, input.Length); 是更快的方法,但最快的方法是根本不复制数组。

如果您不需要单独的二维数组,可以通过函数、属性或自定义类型访问1D数组,就像访问2D数组一样。例如:

class D2<T> {
    T[] input;
    int lenght0;
    public d2(T[] input, int lenght0) {
        this.input = input;
        this.lenght0 = lenght0;
    }
    public T this[int index0, int index1] {
        get { return input[index0 * this.lenght0 + index1]; }
        set { input[index0 * this.lenght0 + index1] = value; }
    }
}

...

byte[] input = { 1, 2, 3, 4 };
var output = new D2<byte>(input, 2);
output[1, 1] = 0;  // now input is { 1, 2, 3, 0 };

此外,在.NET中,访问多维数组比访问锯齿数组略慢一些。

1
Buffer.BlockCopy似乎只适用于基于原始类型的数组,而不是例如object[]。 - TheConstructor

1
通用函数:
private static b[,] to2D<a, b>(a source, valueAt: Func<a, int, b>, int height, int width)
{
    var result = new b[height, width];
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            result[i, j] = valueAt(source, i * width + j);
        }
    }
    return result;
}

var bytes = to2D<byte[], byte>([], (bytes, at) => bytes[at], 10, 20);

1
我知道自己来晚了,但如果你想访问一个一维数组、列表等,就像它是一个n维数组一样(而不需要复制),你可以使用https://github.com/henon/SliceAndDice 来实现这个目的。
// create a 2D array of bytes from a byte[]
var a = new ArraySlice<byte>( new byte[100], new Shape(10,10));
// now access with 2d coordinates
a[7,9]=(byte)56;

当然,对于简单的二维、三维等等,每个人都能够轻松地完成。但是,这个库还可以在不复制的情况下对n维数组进行切片。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接