C# 如何在多维数组中循环?

C# 如何在多维数组中循环?,c#,.net,arrays,c#-4.0,multidimensional-array,C#,.net,Arrays,C# 4.0,Multidimensional Array,string[,]arrayOfMessages正在作为参数传入 我希望能够确定哪些字符串来自arrayOfMessages[0,I]和arrayOfMessages[n,I],其中n是数组的最终索引。不要使用foreach-对循环使用嵌套的,数组的每个维度一个循环 您可以使用该方法获得每个维度中的元素数 请参见MSDN上的。以及嵌套的for循环: foreach (String s in arrayOfMessages) { System.Console.WriteLine(s); }

string[,]arrayOfMessages
正在作为参数传入


我希望能够确定哪些字符串来自
arrayOfMessages[0,I]
arrayOfMessages[n,I]
,其中
n
是数组的最终索引。

不要使用
foreach
-对
循环使用嵌套的
,数组的每个维度一个循环

您可以使用该方法获得每个维度中的元素数


请参见MSDN上的。

以及嵌套的for循环:

foreach (String s in arrayOfMessages)
{
    System.Console.WriteLine(s);
}
for(int row=0;row
只需对
循环使用两个嵌套的
。要获取尺寸标注的尺寸,可以使用:

for(int i=0;i

这假设您实际拥有
字符串[,]
。在.Net中,还可能存在不从0索引的多维数组。在这种情况下,它们必须在C#中表示为
Array
,您需要使用
GetLowerBound()
GetUpperBound()
获取每个维度的边界。

类似的方法可以工作:

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);
    }
}
int length0=arrayOfMessages.GetUpperBound(0)+1;
int length1=arrayOfMessages.GetUpperBound(1)+1;

对于(inti=0;i,可以使用下面的代码运行多维数组

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

看起来您找到了一个适合您的问题的答案,但由于标题要求使用多维数组(我读为2或更多),这是我在搜索该数组时得到的第一个搜索结果,因此我将添加我的解决方案:

foreach (String s in arrayOfMessages)
{
    System.Console.WriteLine("{0}",s);
}
公共静态类多维ArrayExtensions
{
/// 
///通过合并元素的索引,将序列中的每个元素投影到新形式中。
/// 
///数组元素的类型。
///要对其调用操作的值序列。
///应用于每个源元素的操作;函数的第二个参数表示源元素的索引。
公共静态void ForEach(此数组,操作)
{
var dimensionsize=Enumerable.Range(0,array.Rank)。选择(i=>array.GetLength(i)).ToArray();
ArrayForEach(维度大小,动作,新int[]{},数组);
}
私有静态void ArrayForEach(int[]维度大小、动作动作、int[]外部坐标、数组主数组)
{
如果(dimensionSizes.Length==1)
对于(int i=0;i<尺寸[0];i++)
{
var globalCoordinates=externalCoordinates.Concat(新[]{i}).ToArray();
var value=(T)masterArray.GetValue(globalCoordinates);
行动(价值、全球坐标);
}
其他的
对于(int i=0;i<尺寸[0];i++)
ArrayForEach(dimensionSizes.Skip(1).ToArray(),action,externalCoordinates.Concat(new[]{i}).ToArray(),masterArray);
}
公共静态void PopulateArray(此数组,Func calculateElement)
{
ForEach((element,indexArray)=>array.SetValue(calculateElement(indexArray,indexArray));
}
}
用法示例:

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));
    }
}
var foo=新字符串[,]{{“a”,“b”},{“c”,“d”};
foo.ForEach((value,coords)=>Console.WriteLine(“(”+String.Join(“,”,coords)+$”={value}”);
//产出:
//(0,0)=a
//(0,1)=b
//(1,0)=c
//(1,1)=d
//给出一个10d数组,其中每个元素等于其坐标之和:
var bar=新的整数[4,4,4,5,6,5,4,4,5];
bar.PopulateArray(coords=>coords.Sum());

一般的想法是通过维度进行递归。我确信这些函数不会赢得效率奖,但它作为我的晶格的一次性初始化器工作,并带有一个足够好的ForEach,它公开了值和索引。我没有解决的主要缺点是让它自动从数组中识别t,因此需要注意一些当涉及到类型安全时,它会被忽略。

一个更实用的方法是使用LINQ,我总是发现它比循环更好。它使代码更易于维护和可读。下面给出的代码片段显示了使用方法或流畅的LINQ语法的解决方案之一

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());
您也可以使用
of type
而不是
Cast
。它们之间的唯一区别是,对于数据类型混合的集合,当
of type
忽略它无法强制转换的值时,
Cast
将抛出InValidCastException

接下来,我们需要做的就是应用一个忽略(或过滤掉)的LINQ操作符偶数索引处的值。因此,我们使用重载
Where
运算符,其Func委托的类型为
Func
,其中
TSource
是集合中的每个项,
int
是集合中项的索引,
bool
是返回类型


在上面的代码片段中,我使用了一个lambda表达式,它计算每个项索引,只有当它是奇数时才返回true。

为什么不使用带索引的循环呢?
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());
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);
}
{ "Col1", "I am message 1", "Col2", "I am message 2", "Col3", "I am message 3" }