简体   繁体   English

如何在C#中有效地将1D数组复制到3D数组?

[英]How to copy a 1D array to 3D array efficiently in C#?

I have a linear array which I need to reshape as of a stack of 2D data. 我有一个线性数组,需要从一堆2D数据中重塑形状。 In this particular case, the stack only contains one element so the output should be an array with dimensions (height, width, 1). 在这种特殊情况下,堆栈仅包含一个元素,因此输出应为尺寸为(高度,宽度,1)的数组。

This is related to a previous question , where I was asking about the same operation in the other direction (3D to 1D). 这与上一个问题有关 ,我在另一个方向(3D到1D)询问相同的操作。

What is the fastest way to map this data to a 3D array? 将数据映射到3D阵列的最快方法是什么?

I was planning to take the following approach: 我打算采用以下方法:

    public static byte[, ,] ToBuffer3D<TDepth>(this byte[] buffer, int w, int h)
    {
        byte[, ,] buff3D = new byte[h, w, 1];

        for (int i = 0; i < buffer.Length; i++)
        {
            buff3D[(int)Math.Floor(i / (double)w), i % w, 0] = buffer[i];
        }

        return buff3D;
    }

But it seems like it might be possible to take advantage of how the data is already stored in memory to copy more than one element at a time. 但是似乎有可能可以利用数据已存储在内存中的方式来一次复制多个元素。 Is there some other mapping approach that could be employed in C#? 在C#中还可以使用其他映射方法吗?

This is likely to be somewhat faster: 这可能会更快一些:

public static byte[,,] ToBuffer3Da(this byte[] buffer, int w, int h)
{
    byte[,,] buff3D = new byte[h, w, 1];
    Buffer.BlockCopy(buffer, 0, buff3D, 0, h*w);
    return buff3D;
}

if you use the base class and implementation defined below, you have a class that supports both linear and dimensional indexing at the same time. 如果使用下面定义的基类和实现,则您有一个同时支持线性索引和维索引的类。 No conversion or copying is necessary. 无需转换或复制。

Use it like this, 这样使用

var matrix = new DecomposedMatrix<byte>(10, 10, 10)

foreach(var b int matrix)
{
    ...
}

for (var i = 0; i < matrix.Count; i++)
{
    ...
    var item = matrix[i];
    ...
}

for (var x = 0; x < matrix.H; x++)
for (var y = 0; y < matrix.W; y++)
for (var z = 0; z < matrix.D; z++)
{
    ...
    var item = matrix[x, y, z];
    ...
}

classes follow ... 上课...

public abstract class DecomposedMatrix
{
    private readonly int h;
    private readonly int w;
    private readonly int d;

    protected DecomposedMatrix(int h, int w, int d)
    {
        this.h = h;
        this.w = w;
        this.d = d;
    }

    public int W
    {
        get
        {
            return this.w;
        }
    }

    public int D
    {
        get
        {
            return this.d;
        }
    }

    public int H
    {
        get
        {
            return this.h;
        }
    }

    protected int DereferenceCoordinates(int x, int y, int z)
    {
        if (x >= this.H || y >= this.W || z >= this.D)
        {
            throw new IndexOutOfRangeException();
        }

        if (x < 0 || y < 0 || z < 0)
        {
            throw new IndexOutOfRangeException();
        }

        return z + (y * this.D) + (x * this.W * this.D);
    }
}

and the implementation 和实施

public class DecomposedMatrix<T> : DecomposedMatrix, IReadOnlyList<T>
{
    private readonly IList<T> data;

    public DecomposedMatrix(int h, int w, int d)
            : base(h, w, d)
    {
        this.data = new T[h * w * d];
    }

    public T this[int index]
    {
        get
        {
            return this.data[index];
        }

        set
        {
            this.data[index] = value;
        }
    }

    public T this[int x, int y, int z]
    {
        get
        {
            return this.data[this.DereferenceCoordinates(x, y, z)];
        }

        set
        {
            this.data[this.DereferenceCoordinates(x, y, z)] = value;
        }
    }

    public int Count
    {
        get
        {
            return this.data.Count;
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        return this.data.GetEnumerator();
    }

    public IEnumerator IEnumerable.GetEnumerator()
    {
        return this.data.GetEnumerator();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM