首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在一维数组中访问多维?

如何在一维数组中访问多维?
EN

Stack Overflow用户
提问于 2019-03-04 04:46:16
回答 3查看 151关注 0票数 0

我得到了以下代码:

代码语言:javascript
复制
Boo[,,] boos = new Boo[8, 8, 8];
Boo GetMe(int i, int j, int k)
{
    return boos[i, j, k];
}

上面的代码效率很低,所以我将其转换为一维数组:

代码语言:javascript
复制
Boo[] boosone;
Boo[,,] boos = new Boo[8, 8, 8];
Boo GetMe(int i, int j, int k)
{
   if (boosone == null)
   {
       boosone = new Boo[8 * 8 * 8];
       int num = 0;
       for (int x = 0; x < 8; x++)
       {
           for (int y = 0; y < 8; y++)
           {
               for (int z = 0; z < 8; z++)
               {
                   boosone[num] = boos[x, y, z];
                   num++;
               }
           }
       }
    }
    return boosone[?];
}

如何从一维数组boosone中获取Boo (与多维数组j k l中的位置相同)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-03-04 19:15:50

为什么你不看看能提供更好性能的锯齿数组呢?我做了一个测试(在RELEASE configuration下),结果显示包装器比d3数组快两倍,但是d3数组快3倍。

代码语言:javascript
复制
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;

namespace ArrayWrapper
{
    class ArrayPerformanceTest
    {
        int xSize = 2;
        int ySize = 3;
        int zSize = 4;
        int count = 100000000;
        int delay = 500;

        static void Main(string[] args)
        {
            new ArrayPerformanceTest().Run();
        }

        private void Run()
        {

            var d3Array = CreateD3Array();
            var wrapped = GetD1Adapter(d3Array);
            var jagged = GetJaggedArray(d3Array);

            Thread.Sleep(delay);
            TestD3Array(d3Array);
            Thread.Sleep(delay);
            TestWrappedArray(wrapped);
            Thread.Sleep(delay);
            TestJaggeddArray(jagged);
            Thread.Sleep(delay);
        }

        private int[,,] CreateD3Array()
        {
            var rectangular = new int[xSize, ySize, zSize];

            int i = 7;
            for (var x = 0; x < xSize; x++)
                for (var y = 0; y < ySize; y++)
                    for (var z = 0; z < zSize; z++)
                        rectangular[x, y, z] = ++i;

            return rectangular;
        }

        private int[] GetD1Adapter(int[,,] d3Array)
        {
            return d3Array.Cast<int>().ToArray();
        }

        private int[][][] GetJaggedArray(int[,,] d3Array)
        {
            var xSize = d3Array.GetUpperBound(0) + 1;
            var ySize = d3Array.GetUpperBound(1) + 1;
            var zSize = d3Array.GetUpperBound(2) + 1;

            var jagged = new int[xSize].Select(j => new int[ySize].Select(k => new int[zSize].ToArray()).ToArray()).ToArray();

            for (var x = 0; x < xSize; x++)
                for (var y = 0; y < ySize; y++)
                    for (var z = 0; z < zSize; z++)
                        jagged[x][y][z] = d3Array[x, y, z];

            return jagged;
        }

        private void TestD3Array(int[,,] d3Array)
        {
            int i;
            var sw = new Stopwatch();
            sw.Start();
            for (var c = 0; c < count; c++)
                for (var x = 0; x < xSize; x++)
                    for (var y = 0; y < ySize; y++)
                        for (var z = 0; z < zSize; z++)
                            i = d3Array[x, y, z];
            sw.Stop();
            Console.WriteLine($"{nameof(d3Array),7} {sw.ElapsedTicks,10}");
        }

        private void TestWrappedArray(int[] wrapped)
        {
            int i;
            var sw = new Stopwatch();
            sw.Start();
            for (var c = 0; c < count; c++)
                for (var x = 0; x < xSize; x++)
                    for (var y = 0; y < ySize; y++)
                        for (var z = 0; z < zSize; z++)
                            i = wrapped[x * ySize * zSize + y * zSize + z];
            sw.Stop();
            Console.WriteLine($"{nameof(wrapped),7} {sw.ElapsedTicks,10}");
        }

        private void TestJaggeddArray(int[][][] jagged)
        {
            int i;
            var sw = new Stopwatch();
            sw.Start();
            for (var c = 0; c < count; c++)
                for (var x = 0; x < xSize; x++)
                    for (var y = 0; y < ySize; y++)
                        for (var z = 0; z < zSize; z++)
                            i = jagged[x][y][z];
            sw.Stop();
            Console.WriteLine($"{nameof(jagged),7} {sw.ElapsedTicks,10}");
        }
    }
}

输出:

代码语言:javascript
复制
d3Array   15541709
wrapped    8213316
 jagged    5322008

我还分析了CPU的使用情况。

这三种方法的速率都是相同的。

票数 -2
EN

Stack Overflow用户

发布于 2019-03-04 04:56:30

我真的不确定为什么你说第一个3D数组效率不高(我的意思是,你有没有注意到在使用它时速度特别慢?),但你可以通过一些简单的偏移计算来做到这一点。

首先,如果您的目标是最新的C#版本,您可以仅用两行代码替换整个复制功能,然后您的代码将如下所示:

代码语言:javascript
复制
using System;
using System.Runtime.InteropServices;

Boo[] boosone;
Boo[,,] boos = new Boo[8, 8, 8];

Boo GetMe(int i, int j, int k)
{
    if (boosone == null)
    {
        boosone = new Boo[boos.Length];
        MemoryMarshal.CreateSpan(ref boos[0, 0, 0], boosone.Length).CopyTo(boosone);
    }

    return boosone[boos.GetLength(1) * boos.GetLength(2) * i + boos.GetLength(2) * j + k];
}

如果你出于某种原因不想使用MemoryMarshal类,你也可以使用LINQ来展平你的3D数组,尽管这种方法的效率要低得多:

代码语言:javascript
复制
boosone = boos.Cast<Boo>().ToArray();
票数 2
EN

Stack Overflow用户

发布于 2019-03-04 04:59:21

代码语言:javascript
复制
int index = (8 * 8 * i) + (8 * j) + k;
return boosone[index];
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54973574

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档