我有这段代码
private int[, ,] dim(int[] m)
{
ll = 0;
ww = 0;
hh = 0;
// int[, ,] buff3D = new int[ll, ww, hh];
int[, ,] to3dimen = new int[ww, ll, hh];
if ((mm == 1) || (mm == 4) || (mm == 7))
{
ww = 4; ll = 8; hh = 8;
to3dimen = new int[ww, ll, hh];
to3dimen = To3D(m, ww, ll, hh);
}
else if ((mm == 2) || (mm == 5) || (mm == 8))
{
ww = 8; ll = 4; hh = 8;
to3dimen = new int[ww, ll, hh];
to3dimen = To3D(m, ww, ll, hh);
}
else if ((mm == 3) || (mm == 6) || (mm == 9))
{
ww = 8; ll = 8; hh = 4;
to3dimen = new int[ww, ll, hh];
to3dimen = To3D(m, ww, ll, hh);
}
return to3dimen;
}
private int[, ,] To3D(
int[] thisArray,
int width,
int height,
int hig
)
{
int[, ,] array3d = new int[width, height, hig];
int sum = 0;
for (int row = 0; row < width; row++)
{
for (int col = 0; col < height; col++)
{
for (int wid = 0; wid < hig; wid++)
{
array3d[row, col, wid] = thisArray[sum];
sum++;
}
}
}
return array3d;
}
函数To3d
将1D数组转换为3D数组,函数dim
决定3D数组的尺寸是什么(4,8,8或8,8,4或8,4, 8)。
代码工作正常,但执行时间太长(根据文件长度而有所不同)。
如果有可能,我想要一个更快的代码,有人可以帮忙吗?
注意:我考虑过parallel
,但这对我的代码没用。
答案 0 :(得分:4)
这里有很多多余的代码。您只需要to3dimen
To3D()
函数内的一个分配。
但这并不是让你失望的原因。什么让你失望的是使用多维数组。
对于初学者,请将Dim()
清理为
private int[,,] Dim(int[] m)
{
// mm ww ll hh offset=(mm-1)%3
// 1 4 8 8 0
// 2 8 4 8 1
// 3 8 8 4 2
// 4 4 8 8 0
// 5 8 4 8 1
// 6 8 8 4 2
// 7 4 8 8 0
// 8 8 4 8 1
// 9 8 8 4 2
int offset = (mm - 1) % 3;
int ww = offset == 0 ? 4 : 8;
int ll = offset == 1 ? 4 : 8;
int hh = offset == 2 ? 4 : 8;
return To3D(m, ww, ll, hh);
}
但要利用c#的强大功能,您应该创建一个类包或将三个坐标解包为单个数组索引。请考虑以下示例代码:
public class Packed3dArray : IEnumerable<int>
{
readonly int width, height, hig;
readonly int[] array;
public Packed3dArray(int[] array, int mm)
{
int offset = (mm - 1) % 3;
this.width = offset == 0 ? 4 : 8;
this.height = offset == 1 ? 4 : 8;
this.hig = offset == 2 ? 4 : 8;
this.array = array;
}
#region Properties
public int Width => width;
public int Height => height;
public int Hig => hig;
public int Index(int row, int col, int wid) => wid + hig*(col + height*row);
/// <summary>
/// Default indexer with three coordinates
/// </summary>
public int this[int row, int col, int wid]
{
// this is really fast because it is integer math
// and accesses a 1D array which is recommended.
get => array[wid + hig*(col + height*row)];
set => array[wid + hig*(col + height*row)] = value;
}
/// <summary>
/// Default indexer with an index
/// </summary>
public int this[int index]
{
get => array[index];
set => array[index]=value;
}
#endregion
public IEnumerator<int> GetEnumerator()
{
for (int i = 0; i < array.Length; i++)
{
yield return array[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
用作
static void Main(string[] args)
{
int[] array = new int[8 * 8 * 4];
// Use mm=3
Packed3dArray pa = new Packed3dArray(array, 3);
int width = pa.Width // width = 8
int height = pa.Height // height = 8
int hig = pa.Hig // hig = 4
// Set the last element to one using the default indexer (see code).
pa[7, 7, 3] = 1;
// or read a value
var x = pa[255]; // x=1
// Go through all the elements and unpack the (x,y,z) values into an index:
for (int row = 0; row < 8; row++)
{
for (int col = 0; col < 8; col++)
{
for (int wid = 0; wid < 4; wid++)
{
Debug.WriteLine($"[{row},{col},{wid}]=[{pa.Index(row, col, wid)}]={pa[row,col,wid]}");
}
}
}
// Recover the original array by using Enumerable.ToArray() extension
int[] copy = pa.ToArray();
}
结果是:
[0,0,0]=[0]=0
[0,0,1]=[1]=0
[0,0,2]=[2]=0
[0,0,3]=[3]=0
[0,1,0]=[4]=0
[0,1,1]=[5]=0
...
[0,7,3]=[31]=0
[1,0,0]=[32]=0
[1,0,1]=[33]=0
...
[4,7,2]=[158]=0
[4,7,3]=[159]=0
[5,0,0]=[160]=0
[5,0,1]=[161]=0
...
[7,6,3]=[251]=0
[7,7,0]=[252]=0
[7,7,1]=[253]=0
[7,7,2]=[254]=0
[7,7,3]=[255]=1
答案 1 :(得分:0)
我认为你的嵌套for循环评估为O(n ^ 3)时间,所以它肯定会因较大的文件而变慢。
通过此修改,您可能会获得稍快但更难看的结果:
for (int row = 0; row++ < width;)
{
for (int col = 0; col++ < height;)
{
for (int wid = 0; wid++ < hig;)
{
array3d[row, col, wid] = thisArray[sum++];
}
}
}
这与在福特Escort中拍打(蹩脚)涡轮增压器有很大不同。它会稍快一点,但绝不酷;)
请注意, 仍然 O(n ^ 3)。