我有一个3D数组
String[][,] cross = {new String[,]{{"1", "b", "b", "b"}, {"b", "c", "c", "c"}},new String[,]{{"2", "b", "b", "e"}, {"b", "c", "c", "d"}}}
如何迭代这个数组。
我想像这样迭代
foreach(String[,] abc in cross) //abc must be the first/second 2D array
foreach(string[] arr in abc) //arr must hold {"1", "b", "b", "b"} (say)
{
}
我试过了,但没有工作。
答案 0 :(得分:2)
你需要3级嵌套for循环,每个维度一个
答案 1 :(得分:2)
这应该有效:
foreach (string s in cross.SelectMany(x => x.Cast<string>()))
{
// Code goes here.
}
更新:根据您的评论,您似乎希望您的枚举在某个时候处理string[]
,如下所示:
{"1", "b", "b", "b"}
问题是:您声明的数组中不存在此类数组。这可能令人困惑,因为用于声明T[]
数组的语法与用于声明T[,]
数组的语法之间存在重叠。
让我们写出你的初始化,使其更清晰:
string[][,] cross = {
new string[,] {
{"1", "b", "b", "b"},
{"b", "c", "c", "c"}
},
new string[,] {
{"2", "b", "b", "e"},
{"b", "c", "c", "d"}
}
};
我们这里有两个string[,]
维度为4x2的数组。 上方的表达式{"1", "b", "b", "b"}
不代表单个数组,而是多维数组<维>中一维的值。
要实现您似乎想要的行为,Mark Cidade's answer是正确的:您无法使用string[][,]
执行此操作,但您可以使用string[][][]
执行此操作。
string[][][] cross = new[] {
new[] {
new[] {"1", "b", "b", "b"},
new[] {"b", "c", "c", "c"}
},
new[] {
new[] {"2", "b", "b", "e"},
new[] {"b", "c", "c", "d"}
}
};
以上述方式声明cross
可让您执行以下操作:
foreach (string[][] abc in cross)
{
foreach (string[] arr in abc)
{
Console.WriteLine(string.Join(", ", arr));
}
}
或者,借用我原来的建议:
foreach (string[] arr in cross.SelectMany(x => x))
{
Console.WriteLine(string.Join(", ", arr));
}
输出:
1, b, b, b b, c, c, c 2, b, b, e b, c, c, d
答案 2 :(得分:1)
鉴于您的锯齿状的2D数组,您将执行经典迭代,如下所示
foreach (string[,] array in cross)
{
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
string item = array[i, j];
// do something with item
}
}
}
答案 3 :(得分:1)
string[,]
与string[][]
的工作方式不同 - 它是一个正方形数组,而不是一个数组数组。当您在foreach
语句中使用它时,枚举器将为您提供一系列单独的字符串,类似于以下内容:
foreach(string[,] abc in cross)
for(int i=0; i < abc.GetLength(0); ++i)
for(int j=0; j < abc.GetLength(1); ++j)
{ string str = abc[i,j];
}
如果您想要类似于迭代代码的内容,那么您需要string[][][]
而不是string[][,]
:
string[][][] cross = { new string[][]{new string[]{"1", "b", "b", "b"}, new string[]{"b", "c", "c", "c"}}
,new string[][]{new string[]{"2", "b", "b", "e"}, new string[]{"b", "c", "c", "d"}}};
foreach(string[][] abc in cross)
foreach(string[] arr in abc)
{
}
答案 4 :(得分:1)
3D阵列应该以我的方式看起来像这样:
string[, ,] arr = new string[,,]{
{
{"a1", "b1", "c1"},
{"a2", "b2", "c2"},
{"a3", "b3", "c3"},
},{
{"a4", "b4", "c4"},
{"a5", "b5", "c5"},
{"a6", "b6", "c6"},
}
};
可以通过这种方式逐个遍历所有项目:
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
for (int k = 0; k < arr.GetLength(2); k++)
{
string s = arr[i, j, k];
}
}
}
答案 5 :(得分:0)
foreach(String[,] abc in cross)
foreach(string s in abc) //removed [] from inner loop
{
// do something with s
}
}
答案 6 :(得分:0)
听起来你想要的是数组包含2D数组的第二个元素,按第一个元素分组。所以给出你的例子,你想要这样的结果:
Iteration 1a: {"1", "b", "b", "b"} Iteration 1b: {"b", "c", "c", "c"} Iteration 2a: {"2", "b", "b", "e"} Iteration 2b: {"b", "c", "c", "d"}
了解这无法有效实现,因为2D数组不是存储为多个数组,而是存储为单个内存块。在内存中,您的数组将如下所示:
"1", "b", "b", "b", "b", "c", "c", "c", "2", "b", "b", "e", "b", "c", "c", "d"
当您使用a[y, x]
访问它时,y * a.GetLength(0) + x
选择了正确的元素。
如果你真的想要一个数组数组,那么你应该使用[][]
而不是[,]
,这是其他人所建议的。另一方面,如果出于其他原因你仍然坚持使用多维数组,那么你将不得不构建或伪造内部数组。
构建内部数组:
foreach(string[,] square in cross)
for(int y = 0; y < square.GetUpperBound(0); y++){
string[] inner = new string[square.GetLength(1)];
for(int x = 0; x < inner.Length; x++)
inner[x] = square[y, x];
// now do something with inner
}
但这样效率很低,所以你最好假装它。如果您以后只需要迭代它,那么您可以创建一个可枚举:
foreach(string[,] square in cross)
for(int y = 0; y < square.GetUpperBound(0); y++){
var inner = GetEnumeratedInner(square, y);
// now do something with inner
}
...
static IEnumerable<string> GetEnumeratedInner(string[,] square, int y){
for(int x = 0; x < square.GetUpperBound(1); x++)
yield return square[y, x];
}
如果你真的需要通过索引访问它,就像使用数组一样,那么索引类就可以解决这个问题:
foreach(string[,] square in cross)
for(int y = 0; y < square.GetUpperBound(0); y++){
var inner = new IndexedInner(square, y);
// now do something with inner
}
...
// this class should really implement ICollection<T> and System.Collections.IList,
// but that would be too much unimportant code to put here
class IndexedInner<T> : IEnumerable<T>{
T[,] square;
int y;
public IndexedInner(T[,] square, int y){
this.square = square;
this.y = y;
}
public int Length{get{return square.GetLength(1);}}
public T this[int x]{
get{return square[y, x];}
set{square[y, x] = value;}
}
public IEnumerator<T> GetEnumerator(){
for(int x = 0; x < square.GetUpperBound(1); x++)
yield return square[y, x];
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator(){
return GetEnumerator();
}
}