【问题标题】:C# convert 1D array to 2DC# 将一维数组转换为二维
【发布时间】:2020-09-20 00:38:08
【问题描述】:

我发现自己通过执行以下操作将 1D 字节和单个数组转换为 2D。我怀疑它可能和其他方法一样快,但也许有更简洁的范例? (林克?)

    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[]吗?
  • 您能否提供其中一项功能的示例输入/输出?

标签: c# linq


【解决方案1】:

这无助于使方法中的代码更简洁,但我注意到您有 2 个基本相同的方法,它们的区别仅在于它们的类型。我建议使用generics

这将使您只定义一次方法。使用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() 更快更简单。自框架 1.1 以来一直存在
  • @dynamichael 仅在您的类型实际上具有以字节为单位的恒定大小时才有效。对于string
【解决方案2】:

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

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

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 中访问多维数组比访问交错数组要慢一些

【讨论】:

  • Buffer.BlockCopy 似乎只适用于基于原始类型的数组,而不是例如对象[]。
【解决方案3】:

通用函数:

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);

【讨论】:

    【解决方案4】:

    我知道我迟到了,但是如果您想访问一维数组、列表等,就像它是一个 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;
    

    当然,每个人都可以轻松完成简单的 2d、3d、... nd 卷。但是这个库也允许在不复制的情况下对 n 维数组进行切片。

    【讨论】:

      猜你喜欢
      • 2021-11-23
      • 2020-03-26
      • 1970-01-01
      • 2012-03-08
      • 2016-02-18
      • 2018-02-19
      相关资源
      最近更新 更多