C# 用一维索引访问多维数组
请参阅下面的代码片段。使用一维索引访问多维数组的方法是什么。Foreach可以做到这一点。是的,我知道,收益率和指数是不一样的。我应该使用foreach并创建一个新数组吗?或者我可以在不创建新阵列的情况下执行此操作吗C# 用一维索引访问多维数组,c#,.net,C#,.net,请参阅下面的代码片段。使用一维索引访问多维数组的方法是什么。Foreach可以做到这一点。是的,我知道,收益率和指数是不一样的。我应该使用foreach并创建一个新数组吗?或者我可以在不创建新阵列的情况下执行此操作吗 int[,] myArray = new int[2, 2]; myArray[0,0] = 1; myArray[1,1] = 2; myArray[0,0] = 3; myArray[1,1] = 4; foreach (var
int[,] myArray = new int[2, 2];
myArray[0,0] = 1;
myArray[1,1] = 2;
myArray[0,0] = 3;
myArray[1,1] = 4;
foreach (var value in myArray)
{
Console.Write(value);
}
var valueAtIndex = myArray[2]; //Won't compile, error: Wrong number of indices inside []; expected 2
如果一维索引是指按从上到下、从左到右的顺序围绕多维数组行的索引,则可以使用以下公式计算
x
和y
:
x = index % width
y = index / width
如果一维索引是指按从上到下、从左到右的顺序围绕多维数组行的索引,则可以使用以下公式计算
x
和y
:
x = index % width
y = index / width
从另一端把它挖出来怎么样
int rows=2, cols=2;
int[] myArray = new int[rows*cols];
public void setMyArray(int[] myArray, int x, int y, int value)
{
myArray[(y)*cols + x] = value;
}
setMyArray(0,0,1);
setMyArray(0,1,2);
setMyArray(1,0,3);
setMyArray(1,1,4);
从另一端把它挖出来怎么样
int rows=2, cols=2;
int[] myArray = new int[rows*cols];
public void setMyArray(int[] myArray, int x, int y, int value)
{
myArray[(y)*cols + x] = value;
}
setMyArray(0,0,1);
setMyArray(0,1,2);
setMyArray(1,0,3);
setMyArray(1,1,4);
至于枚举器,它非常简单——它只允许顺序访问。在内部,它保存一个索引数组并逐个递增。它没有使用任何黑客手段使数组成为一维或任何东西——这将是对框架保证的一种丑陋的违反。而且也没有收益,这是在收益实现之前很久写的:) 当然,你可以自己编写这样的黑客程序,使用
safe
code。然而,这是一个非常糟糕的主意。您并不知道这些数组在内存中是如何组织的——这是运行时的一个实现细节。别这样
相反,找出一个合理的寻址模式。如果只有一个索引是有意义的,那么为什么数组首先是多维的呢?如果多维数组是有意义的,为什么要以一维方式访问它
如果它确实有意义,出于某种原因,您可能希望围绕某个内部数组创建自己的包装器类,而不仅仅是使用数组。这很简单
public class DualAccessArray<T>
{
private readonly T[,] _internalArray;
private readonly int _width;
private readonly int _height;
public DualAccessArray(int width, int height)
{
_width = width;
_height = height;
_internalArray = new T[width, height];
}
public T this[long index]
{
get { return _internalArray[index / _width, index % _width]; }
set { _internalArray[index / _width, index % _width] = value; }
}
public T this[int x, int y]
{
get { return _internalArray[x, y]; }
set { _internalArray[x, y] = value; }
}
}
公共类DualAccessArray
{
私有只读T[,]\u内部数组;
私有只读整数宽度;
专用只读int_高度;
公共DualAccessArray(整数宽度、整数高度)
{
_宽度=宽度;
_高度=高度;
_internalArray=新的T[宽度、高度];
}
这是什么[长索引]
{
获取{return _internalArray[index/_width,index%_width];}
设置{u internalArray[index/\u width,index%\u width]=value;}
}
公共T这个[int x,int y]
{
获取{return _internalArray[x,y];}
设置{u internalArray[x,y]=value;}
}
}
然后你可以像这样使用它
var ar = new DualAccessArray<string>(10, 10);
ar[15] = "Hi!";
Console.WriteLine(ar[1, 5]);
var-ar=新的DualAccessArray(10,10);
ar[15]=“嗨!”;
控制台写入线(ar[1,5]);
你可以根据自己的需要来做。例如,使用不同类型的寻址和内存布局可能更有意义,使用一维数组可能更有意义,您可能希望包装现有数组。。。这完全取决于您实际要做什么。至于枚举器,它非常简单-它只允许顺序访问。在内部,它保存一个索引数组并逐个递增。它没有使用任何黑客手段使数组成为一维或任何东西——这将是对框架保证的一种丑陋的违反。而且也没有收益,这是在收益实现之前很久写的:) 当然,你可以自己编写这样的黑客程序,使用
safe
code。然而,这是一个非常糟糕的主意。您并不知道这些数组在内存中是如何组织的——这是运行时的一个实现细节。别这样
相反,找出一个合理的寻址模式。如果只有一个索引是有意义的,那么为什么数组首先是多维的呢?如果多维数组是有意义的,为什么要以一维方式访问它
如果它确实有意义,出于某种原因,您可能希望围绕某个内部数组创建自己的包装器类,而不仅仅是使用数组。这很简单
public class DualAccessArray<T>
{
private readonly T[,] _internalArray;
private readonly int _width;
private readonly int _height;
public DualAccessArray(int width, int height)
{
_width = width;
_height = height;
_internalArray = new T[width, height];
}
public T this[long index]
{
get { return _internalArray[index / _width, index % _width]; }
set { _internalArray[index / _width, index % _width] = value; }
}
public T this[int x, int y]
{
get { return _internalArray[x, y]; }
set { _internalArray[x, y] = value; }
}
}
公共类DualAccessArray
{
私有只读T[,]\u内部数组;
私有只读整数宽度;
专用只读int_高度;
公共DualAccessArray(整数宽度、整数高度)
{
_宽度=宽度;
_高度=高度;
_internalArray=新的T[宽度、高度];
}
这是什么[长索引]
{
获取{return _internalArray[index/_width,index%_width];}
设置{u internalArray[index/\u width,index%\u width]=value;}
}
公共T这个[int x,int y]
{
获取{return _internalArray[x,y];}
设置{u internalArray[x,y]=value;}
}
}
然后你可以像这样使用它
var ar = new DualAccessArray<string>(10, 10);
ar[15] = "Hi!";
Console.WriteLine(ar[1, 5]);
var-ar=新的DualAccessArray(10,10);
ar[15]=“嗨!”;
控制台写入线(ar[1,5]);
你可以根据自己的需要来做。例如,使用不同类型的寻址和内存布局可能更有意义,使用一维数组可能更有意义,您可能希望包装现有数组。。。这完全取决于您实际尝试执行的操作。如果您不仅希望读取值,还希望按照
foreach
遍历数组的相同顺序设置值,则可以使用以下通用索引器类:
public class ArrayIndexer
{
readonly int totalLength;
readonly int lastIndexLength;
readonly int[] lengths;
readonly int[] lowerBounds;
int current;
readonly int[] currentZeroBased;
public ArrayIndexer(int[] lengths, int[] lowerBounds)
{
lastIndexLength = lengths[lengths.Length - 1];
totalLength = lengths[0];
for (int i = 1; i < lengths.Length; i++)
{
totalLength *= lengths[i];
}
this.lengths = lengths;
this.lowerBounds = lowerBounds;
currentZeroBased = new int[lengths.Length];
current = -1;
}
public bool MoveNext()
{
current++;
if (current != 0)
{
int currLastIndex = current % lastIndexLength;
currentZeroBased[currentZeroBased.Length - 1] = currLastIndex;
if (currLastIndex == 0)
{
for (int i = currentZeroBased.Length - 2; i >= 0; i--)
{
currentZeroBased[i]++;
if (currentZeroBased[i] != lengths[i])
break;
currentZeroBased[i] = 0;
}
}
}
return current < totalLength;
}
public int[] Current
{
get
{
int[] result = new int[currentZeroBased.Length];
for (int i = 0; i < result.Length; i++)
{
result[i] = currentZeroBased[i] + lowerBounds[i];
}
return result;
}
}
}
如果您不仅希望读取值,还希望按照
foreach
遍历数组的相同顺序设置值,则可以使用以下常规索引器类:
public class ArrayIndexer
{
readonly int totalLength;
readonly int lastIndexLength;
readonly int[] lengths;
readonly int[] lowerBounds;
int current;
readonly int[] currentZeroBased;
public ArrayIndexer(int[] lengths, int[] lowerBounds)
{
lastIndexLength = lengths[lengths.Length - 1];
totalLength = lengths[0];
for (int i = 1; i < lengths.Length; i++)
{
totalLength *= lengths[i];
}
this.lengths = lengths;
this.lowerBounds = lowerBounds;
currentZeroBased = new int[lengths.Length];
current = -1;
}
public bool MoveNext()
{
current++;
if (current != 0)
{
int currLastIndex = current % lastIndexLength;
currentZeroBased[currentZeroBased.Length - 1] = currLastIndex;
if (currLastIndex == 0)
{
for (int i = currentZeroBased.Length - 2; i >= 0; i--)
{
currentZeroBased[i]++;
if (currentZeroBased[i] != lengths[i])
break;
currentZeroBased[i] = 0;
}
}
}
return current < totalLength;
}
public int[] Current
{
get
{
int[] result = new int[currentZeroBased.Length];
for (int i = 0; i < result.Length; i++)
{
result[i] = currentZeroBased[i] + lowerBounds[i];
}
return result;
}
}
}
Foreach可以做到这一点
不,不能。真的没有类比
由于多维数组实际上是一个具有多个维度的数组,因此有三个选项