2

ギザギザの配列を実行できるようにしようとしていますが、配列の深さが一定ではありません。配列内の各オブジェクトをきれいに処理する方法を探しています。現在、ケースのランクを int として取得することで、さまざまなレベルを処理できる単純なスイッチ ケースがあります。

ただし、配列が 2 レベルの深さの場合もあれば、5 レベルの深さの場合もあります。深さレベルごとにケースを書く必要はありません。

たとえば、myObj という名前のオブジェクトがあり、myObj[] または myObj[][] または myObj[][][][] の場合もあります。

foreach または IEnumerator のいずれかを使用すると、配列の最初の次元のみが走査されます

4

4 に答える 4

4

ギザギザ/多次元配列をトラバースする拡張メソッドを次に示します (David B. one に似ていますが、yield、null 処理、および型キャストを使用します)。

public static class Extensions
{
    public static IEnumerable<T> Traverse<T>(this Array array)
    {
        foreach (object val in array)
        {
            if (val == null)
                continue; //null means empty sub-array --> skip it
            if (val is Array)
            {
                var subArray = (Array)val;
                foreach (var value in subArray.Traverse<T>())
                    yield return value;
            }
            else
            {
                yield return (T)val;
            }
        }
    }
}

使用例:

class Program
{
    static void Main(string[] args)
    {
        int[][][] jagged = new int[4][][];

        jagged[0] = new int[2][] { new[] { 0, 1 }, new[] { 2, 3, 4 } };
        jagged[1] = new int[3][] { new[] { 5, 6, 7 }, new[] { 8, 9, 10 }, new[] { 11, 12 } };
        jagged[3] = new int[4][] { new[] { 13, 14 }, null, new[] { 15, }, new[] { 16 } };

        var jaggedElements = jagged.Traverse<int>().ToList();
        // contains:  1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16

       int[, ,] multi = new[, ,] { { { 1, 2 }, { 3, 4 } },
                        { { 4, 5 }, { 6, 7 } }, 
                        { { 8, 9 }, { 10, 11 } } };


       var multiElements = multi.Traverse<int>().ToList();
       // contains:  1,2,3,4,5,6,7,8,9,10,11

    }
}
于 2011-02-03T16:07:37.653 に答える
3

これでうまくいくはずです。. .

private static void EnumerateObjects(Array items)
{
    foreach (var item in items)
    {
        if (item is Array)
        {
            EnumerateObjects((Array)item);
        }
        else if (item is MyObject)
        {
            Console.WriteLine(item);
        }
    }
}
于 2011-02-03T15:53:22.493 に答える
1

このようなもの?

    static void Main(string[] args)
    {
        int[][][] x = new int[][][]
        {
            new int[][]
            {
                new int [] { 1, 2, 3, 4 },
                new int [] { 5, 6 },
                new int [] { 7 }
            },
            new int[][]
            {
                new int [] { 8 },
                new int [] { 9, 10 },
                new int [] { 11, 12, 13, 14 }
            }
        };

        DeepEnumerateArray(x);
        Console.ReadLine();
    }

    static void DeepEnumerateArray(Array x)
    {
        if (x.Length == 0)
            return;

        object first = x.GetValue(0);
        if (first is Array)
        {
            foreach (Array y in x)
                DeepEnumerateArray(y);
        }
        else
        {
            foreach (object z in x)
                Console.WriteLine(z);
        }
    }
于 2011-02-03T15:45:37.393 に答える
0

あなたの答えは再帰です。これはうまくいかないと思います。子コレクションを持つクラスがあればうまくいきます。

int main()
{
    CheckObj(myObject, 0);
}

void CheckObj(object myObject, int level)
{
    if(!(myObject is myObj[]))
    {
        foreach(myObj[] o in (myObj[][])myObject)
        {
            CheckObj(o, level + 1);
        }
    }
    else
    {
        //do what you need to do with myObj[]
    }
}
于 2011-02-03T15:41:01.013 に答える