質問

I am building a Class DLL that will accept both rectangular and jagged arrays (1D, 2D, 3D, etc. or jagged arrays, jagged array of jagged arrays, etc.). A For Each Item in RectangularArray takes care of the rectangular array, but what about the jagged array? With a For Each Item in JaggedArray loop, Item because an Array. A For I As Integer = 0 to JaggedArray.GetUpperBound(0) works fine for a jagged array, but what if the input was a jagged array of jagged arrays ()()(), or ()()()(), or ()()()()(), etc. etc. etc.?

**edit Based on Jods answer, I've come up with:

Public Shared Function Flatten(source As IEnumerable(Of Object)) As Object
    For Each item As Object In source
        If TypeOf item Is IEnumerable(Of Object) Then
            For Each item2 As Object In Flatten(item)
                Return item2
            Next
        Else
            Return item
        End If
    Next
End Function

and

For Each x In Flatten(ListOfTables)
    If Not Tables.Contains(x) Then Tables.Add(x)
Next

but it is crashing with a "Unable to cast object of type 'System.Char' to type 'System.Collections.IEnumerable'." on the For Each x In Flatten(ListOfTables).

This is completely new to me, any ideas what I'm doing wrong? The first entry it returns is "c"c but I want it to return the full string, or "constraintenode".

役に立ちましたか?

解決

If you know at coding time how deep your jagged arrays are, you can simply use nested loops. See Hans Passant answer for an example of that.

If you don't, you can rely on a type check and recursion. There are various solution, here is a simple one. Sorry I'm writing C# code because without a compiler at hand my VB.NET is a bit flaky; I'm sure you'll get the idea and convert the code easily.

public static IEnumerable Flatten(this IEnumerable source)
{
   foreach (object item in source)
   {
     if (item is IEnumerable)
     {
       foreach (object item2 in Flatten((IEnumerable)item))
         yield return item2;
     }
     else
       yield return item;
   }
}

This code is pretty generic in that it handles any kind of IEnumerable. You can be more restrictive in your checks and accept arrays of a specific type only. This might be important if you expect your arrays to contains list or other IEnumerable|s that you don't want to flatten.

Now just iterate:

For Each x In Flatten(myArray)
  ' Do something with x
Next For
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top