高性能串联二维数组存储为子数组[关闭]

2024-03-16

想象一下,我们有几个由 X Y 坐标标识的 3x3 2D 数组。

伪代码:

Array 0-0     Array 1-0
[[1,2,1]      [[1,2,1]  
 [2,3,2]       [2,3,2]
 [3,1,2]]      [3,1,2]]
 
Array 0-1     Array 1-1
[[1,2,1]      [[1,2,1]  
 [2,3,2]       [2,3,2]
 [3,1,2]]      [3,1,2]]

我们还有一个索引数组,用于索引所有这些子数组。

chunk_array = [
   [Array 0-0, Array 0-1],
   [Array 1-0, Array 1,1]
]

问题是如何快速创建一个包含所有子数组的最终数组(6x6),而不必迭代数组的所有元素,因为这是一个非常关键的地方,必须在尽可能短的时间内进行操作。

那么问题是:执行此操作的最快方法是什么?我查看了缓冲区复制,但仍然不确定这里最好的方法是什么。


这是基于建议的解决方案阿列克谢·列文科夫 https://stackoverflow.com/users/477420/alexei-levenkov在评论中。从他的评论来看:做某事最快的方法就是根本不做...这对你的情况有效吗(即通过将所有 4 个都包装到一个以你喜欢的方式公开索引的类中)?

您创建四个单独的数组,然后将它们添加到能够将这些数组保存在矩形数组中的包装器中。我使用一个函数来访问各个元素,但您可以使用索引器来代替(如果您倾向于这种方式 - 我不喜欢,该访问器对于简单的索引器来说似乎有点太复杂)。

这是主要的类:

public class CompositeArray<T> where T:new()
{
    private readonly T[,][,] _componentArray = null;

    public int IndividualArrayWidth { get; }
    public int IndividualArrayHeight { get; }
    public int ComponentArrayWidth { get; }
    public int ComponentArrayHeight { get;  }
    public int OverallArrayWidth => IndividualArrayWidth * ComponentArrayWidth;
    public int OverallArrayHeight => IndividualArrayHeight * ComponentArrayHeight;

    public CompositeArray(int individualArrayWidth, int individualArrayHeight, int componentArrayWidth,
        int componentArrayHeight)
    {
        IndividualArrayWidth = individualArrayWidth;
        IndividualArrayHeight = individualArrayHeight;
        ComponentArrayWidth = componentArrayWidth;
        ComponentArrayHeight = componentArrayHeight;
        _componentArray = new T[ComponentArrayWidth, ComponentArrayHeight][,];
    }

    public void SetIndividualArray(int x, int y, T[,] array)
    {
        if (x < 0 || x >= IndividualArrayWidth)
        {
            throw new ArgumentOutOfRangeException(nameof(x), x, $@"Must be between 0 and {IndividualArrayWidth - 1}");
        }
        if (y < 0 || y >= IndividualArrayHeight)
        {
            throw new ArgumentOutOfRangeException(nameof(y), y, $@"Must be between 0 and {IndividualArrayHeight - 1}");
        }
        if (array.GetLength(0) != IndividualArrayWidth || array.GetLength(1) != IndividualArrayHeight)
        {
            throw new ArgumentOutOfRangeException(nameof(array),  $@"Must be between an array that is {IndividualArrayWidth} by {IndividualArrayHeight}");
        }

        _componentArray[x, y] = array;
    }

    public T GetOverallElement(int x, int y)
    {
        if (x < 0 || x >= OverallArrayWidth)
        {
            throw new ArgumentOutOfRangeException(nameof(x), x, $@"Must be between 0 and {OverallArrayWidth - 1}");
        }
        if (y < 0 || y >= OverallArrayHeight)
        {
            throw new ArgumentOutOfRangeException(nameof(y), y, $@"Must be between 0 and {OverallArrayHeight - 1}");
        }

        int whichArrayX = x / IndividualArrayWidth;
        int innerX = x % IndividualArrayWidth;
        int whichArrayY = y / IndividualArrayHeight;
        int innerY = y % IndividualArrayHeight;

        return (_componentArray[whichArrayX, whichArrayY][innerX, innerY]);
    }
}

请注意,我创建了一个矩形锯齿状矩形阵列。花了一些时间才弄清楚语法。

请注意,根本没有复制。对于每个元素访问,您只需支付两次整数除法和两次整数模运算的费用。如果您只使用 2x2 数组,则可以将其减少为两个位移位和两个位测试(因为除以二是一个简单的位移位,而检查偶数/奇数只是对最低有效位的测试)。

下面是一些练习该类的代码:

 int[,] array00 = new int[,]
 {
     {1, 2, 3},
     {4, 5, 6},
     {7, 8, 9}
 };
 int[,] array01 = new int[,]
 {
     {11, 12, 13},
     {14, 15, 16},
     {17, 18, 19}
 };
 int[,] array10 = new int[,]
 {
     {21, 22, 23},
     {24, 25, 26},
     {27, 28, 29}
 };
 int[,] array11 = new int[,]
 {
     {31, 32, 33},
     {34, 35, 36},
     {37, 38, 39}
 };

 CompositeArray<int> bigArray = new CompositeArray<int>(array00.GetLength(0), array00.GetLength(1), 2,2);
 bigArray.SetIndividualArray(0, 0, array00);
 bigArray.SetIndividualArray(0, 1, array01);
 bigArray.SetIndividualArray(1, 0, array10);
 bigArray.SetIndividualArray(1, 1, array11);

 var shouldBe2 = bigArray.GetOverallElement(0, 1);
 var shouldBe6 = bigArray.GetOverallElement(1, 2);
 var shouldBe28 = bigArray.GetOverallElement(5, 1);
 var shouldBe16 = bigArray.GetOverallElement(1, 5);
 var shouldBe32 = bigArray.GetOverallElement(3, 4);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

高性能串联二维数组存储为子数组[关闭] 的相关文章

  • EF Core Group By 翻译支持条件总和

    听说 EF Core 2 1 将支持翻译小组 我感到非常兴奋 我下载了预览版并开始测试它 但发现我在很多地方仍然没有得到翻译分组 在下面的代码片段中 对 TotalFlagCases 的查询将阻止翻译分组工作 无论如何 我可以重写这个以便我
  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐