c# - 存储为子数组的高性能连接二维数组
问题描述
想象一下,我们有几个由 XY 坐标标识的 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 最终数组,而无需迭代数组的所有元素,因为这是一个非常关键的地方,必须在尽可能短的时间内运行。
所以问题:执行此操作的最快方法是什么?我看过缓冲区副本,但仍然不确定这里最好的方法是什么。
解决方案
这是基于评论中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);
推荐阅读
- jquery - 用户仅在具有特定类名的 div 之前/之后附加
- java - 如何实现 Comparable 接口?
- android - RecyclerView 行中未显示效果
- hadoop - 共享外部配置单元元存储如何依赖特定版本的 HDInsight(Hadoop) 群集?
- php - 如果复选框被禁用,则更改文本颜色
- jquery - $(...).datepicker 不是 Rails 6 中的函数
- javascript - 减少 Typescript/JS 中嵌套对象数组的级别
- mysql - 如何将 MySQL 中的记录设置到 datagridview 的列中?
- image - 没有显示带有 JavaFX 的图像
- php - 使用 php 打印多维数组,数组以关联格式存储