2010-09-03 28 views
2

我有3D阵列如何循环3D String数组,在C#中

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) 
    { 
    } 

我尝试这样做,但没有工作。

+1

您目前具有2D阵列的锯齿形阵列。** – 2010-09-03 12:37:13

+1

我建议使用对象或字符串来代替3D阵列的列表,将通过 – Gage 2010-09-03 13:22:44

回答

1

鉴于你二维数组的交错数组,你想执行的经典迭代以下

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 
     } 
    } 
} 
+0

这肯定有效。一个破解。 – Vinod 2010-09-03 12:47:04

2

你需要循环3个级别的嵌套,每个维度

2

这应该工作:

foreach (string s in cross.SelectMany(x => x.Cast<string>())) 
{ 
    // Code goes here. 
} 

UPDATE:基于您的评论,它看起来像你想为你的枚举在某些时候对付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"} 
    } 
}; 

我们这里是什么尺寸的4×2两种string[,]阵列。表达式{"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 
+0

每个元件可以被提取容易进行迭代这条路。 对我的原始要求有更多建议。 – Vinod 2010-09-03 12:43:24

+0

@Vinod:对不起,错过了你最初的目标。我会更新。 – 2010-09-03 12:52:54

+0

+1简单和使用LINQ – Gage 2010-09-03 13:35:34

0
foreach(String[,] abc in cross) 
    foreach(string s in abc) //removed [] from inner loop 
    { 
     // do something with s 
    } 
} 
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) 
    { 
    } 
1

3D阵列应该像这样在我的方式:

string[, ,] arr = new string[,,]{ 
    { 
     {"a1", "b1", "c1"}, 
     {"a2", "b2", "c2"}, 
     {"a3", "b3", "c3"}, 
    },{ 
     {"a4", "b4", "c4"}, 
     {"a5", "b5", "c5"}, 
     {"a6", "b6", "c6"}, 
    } 
}; 

和我通过全项逐一可以通过这种方式来完成terating:

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]; 
     } 
    } 
} 
0

这听起来像你想要的是直到结束是阵列包含二维数组的第二个要素,第一要素组合。因此,考虑你的榜样,你想要的结果是这样的:

 
Iteration 1a: {"1", "b", "b", "b"} 
Iteration 1b: {"b", "c", "c", "c"} 
Iteration 2a: {"2", "b", "b", "e"} 
Iteration 2b: {"b", "c", "c", "d"} 

明白这不能被有效地实现,因为一个二维数组没有被存储为多个阵列,而是作为一个内存块奇异。在内存方面,你的阵列会看这本:

 
"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(); 
    } 
}