C# 如何遍历多维数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9301109/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you loop through a multidimensional array?
提问by orange
foreach (String s in arrayOfMessages)
{
System.Console.WriteLine(s);
}
string[,] arrayOfMessagesis being passed in as a parameter.
string[,] arrayOfMessages正在作为参数传入。
I want to be able to determine which strings are from arrayOfMessages[0,i]and arrayOfMessages[n,i], where nis the final index of the array.
我希望能够确定哪些字符串来自arrayOfMessages[0,i]and arrayOfMessages[n,i],n数组的最终索引在哪里。
采纳答案by svick
Simply use two nested forloops. To get the sizes of the dimensions, you can use GetLength():
只需使用两个嵌套for循环。要获得尺寸的大小,您可以使用GetLength():
for (int i = 0; i < arrayOfMessages.GetLength(0); i++)
{
for (int j = 0; j < arrayOfMessages.GetLength(1); j++)
{
string s = arrayOfMessages[i, j];
Console.WriteLine(s);
}
}
This assumes you actually have string[,]. In .Net it's also possible to have multidimensional arrays that aren't indexed from 0. In that case, they have to be represented as Arrayin C# and you would need to use GetLowerBound()and GetUpperBound()the get the bounds for each dimension.
这假设您实际上拥有string[,]. 在 .Net 中,也可能有不从 0 开始索引的多维数组。在这种情况下,它们必须Array在 C# 中表示,并且您需要使用GetLowerBound()并GetUpperBound()获取每个维度的边界。
回答by Oded
Don't use foreach- use nested forloops, one for each dimension of the array.
不要使用foreach- 使用嵌套for循环,数组的每个维度一个。
You can get the number of elements in each dimension with the GetLengthmethod.
您可以使用该GetLength方法获取每个维度中的元素数量。
See Multidimensional Arrays (C# Programming Guide)on MSDN.
请参阅MSDN 上的多维数组(C# 编程指南)。
回答by Henk Holterman
With a nested for loop:
使用嵌套的 for 循环:
for (int row = 0; row < arrayOfMessages.GetLength(0); row++)
{
for (int col = 0; col < arrayOfMessages.GetLength(1); col++)
{
string message = arrayOfMessages[row,col];
// use the message
}
}
回答by Igor ostrovsky
Something like this would work:
像这样的事情会起作用:
int length0 = arrayOfMessages.GetUpperBound(0) + 1;
int length1 = arrayOfMessages.GetUpperBound(1) + 1;
for(int i=0; i<length1; i++) { string msg = arrayOfMessages[0, i]; ... }
for(int i=0; i<length1; i++) { string msg = arrayOfMessages[length0-1, i]; ... }
回答by user3428474
You can use the code below to run multidimensional arrays.
您可以使用下面的代码来运行多维数组。
foreach (String s in arrayOfMessages)
{
System.Console.WriteLine("{0}",s);
}
回答by dananski
It looks like you found an answer suitable for your problem, but since the title asks for a multidimensional array (which I read as 2 or more), and this is the first search result I got when searching for that, I'll add my solution:
看起来您找到了适合您的问题的答案,但是由于标题要求提供一个多维数组(我读为 2或更多),这是我在搜索时得到的第一个搜索结果,我将添加我的解决方案:
public static class MultidimensionalArrayExtensions
{
/// <summary>
/// Projects each element of a sequence into a new form by incorporating the element's index.
/// </summary>
/// <typeparam name="T">The type of the elements of the array.</typeparam>
/// <param name="array">A sequence of values to invoke the action on.</param>
/// <param name="action">An action to apply to each source element; the second parameter of the function represents the index of the source element.</param>
public static void ForEach<T>(this Array array, Action<T, int[]> action)
{
var dimensionSizes = Enumerable.Range(0, array.Rank).Select(i => array.GetLength(i)).ToArray();
ArrayForEach(dimensionSizes, action, new int[] { }, array);
}
private static void ArrayForEach<T>(int[] dimensionSizes, Action<T, int[]> action, int[] externalCoordinates, Array masterArray)
{
if (dimensionSizes.Length == 1)
for (int i = 0; i < dimensionSizes[0]; i++)
{
var globalCoordinates = externalCoordinates.Concat(new[] { i }).ToArray();
var value = (T)masterArray.GetValue(globalCoordinates);
action(value, globalCoordinates);
}
else
for (int i = 0; i < dimensionSizes[0]; i++)
ArrayForEach(dimensionSizes.Skip(1).ToArray(), action, externalCoordinates.Concat(new[] { i }).ToArray(), masterArray);
}
public static void PopulateArray<T>(this Array array, Func<int[], T> calculateElement)
{
array.ForEach<T>((element, indexArray) => array.SetValue(calculateElement(indexArray), indexArray));
}
}
Usage example:
用法示例:
var foo = new string[,] { { "a", "b" }, { "c", "d" } };
foo.ForEach<string>((value, coords) => Console.WriteLine("(" + String.Join(", ", coords) + $")={value}"));
// outputs:
// (0, 0)=a
// (0, 1)=b
// (1, 0)=c
// (1, 1)=d
// Gives a 10d array where each element equals the sum of its coordinates:
var bar = new int[4, 4, 4, 5, 6, 5, 4, 4, 4, 5];
bar.PopulateArray(coords => coords.Sum());
General idea is to recurse down through dimensions. I'm sure the functions won't win efficiency awards, but it works as a one-off initialiser for my lattice and comes with a nice-enough ForEach that exposes the values and indices. Main downside I haven't solved is getting it to automatically recognise T from the Array, so some caution is required when it comes to the type safety.
一般的想法是通过维度向下递归。我确信这些函数不会赢得效率奖,但它可以作为我的格子的一次性初始化器,并带有一个足够好的 ForEach 来公开值和索引。我还没有解决的主要缺点是让它自动从数组中识别 T,因此在类型安全方面需要谨慎。
回答by r4k35h
A more functional approach would be to use LINQ, which I always find better than loops. It makes the code more maintainable and readable. The below given code snippet shows one of the solution using Method or Fluent LINQ syntax.
一种更实用的方法是使用 LINQ,我总是发现它比循环更好。它使代码更具可维护性和可读性。下面给出的代码片段显示了使用 Method 或 Fluent LINQ 语法的解决方案之一。
string[,] arrayOfMessages = new string[3, 2] { { "Col1","I am message 1" }, { "Col2", "I am message 2" }, { "Col3", "I am message 3" } };
var result = arrayOfMessages.Cast<string>()
.Where((msg, index) => index % 2 > 0);
foreach (var msg in result)
{
Console.WriteLine(msg);
}
LINQ extension methods are not available to multi-dimensional arrays since they do not implement IEnumerable<T>interface. That's where Cast<T>comes into picture. It basically casts the whole array into IEnumerable<T>. In our case it will flatten out the multi-dimensional array into IEnumerable<string>something like:
LINQ 扩展方法不适用于多维数组,因为它们不实现IEnumerable<T>接口。这Cast<T>就是进入图片的地方。它基本上将整个数组转换为IEnumerable<T>. 在我们的例子中,它将把多维数组展平成IEnumerable<string>类似的东西:
{ "Col1", "I am message 1", "Col2", "I am message 2", "Col3", "I am message 3" }
You can also use OfType<T>instead of Cast<T>. The only difference between them is that in case of collections with mixed data types, while OfType<T>ignores values which it is unable to cast, Cast<T>will throw an InValidCastException.
您也可以使用OfType<T>代替Cast<T>。它们之间的唯一区别是,在具有混合数据类型的集合的情况下,在OfType<T>忽略无法转换的值时,Cast<T>将抛出 InValidCastException。
Next, all we need to do is to apply a LINQ operator that ignores (or filters out) values at even indices. So we use an overload of Whereoperator whose Func delegate is of the type Func<TSource, int, bool>, where TSourceis each item in the collection, intis the index of the item in the collection and boolis the return type.
接下来,我们需要做的就是应用一个 LINQ 运算符,该运算符忽略(或过滤掉)偶数索引处的值。因此,我们使用Where运算符的重载,其 Func 委托的类型为Func<TSource, int, bool>,其中TSource是集合中的每个项目,是集合中项目int的索引,bool是返回类型。
In the above snippet, I used a lambda expression which evaluates each item index and returns true only when it is an odd number.
在上面的代码片段中,我使用了一个 lambda 表达式,它计算每个项目索引并仅在它是奇数时返回 true。

