不规则数组的通用打印

3

我目前正在处理大量的数组,并为了调试目的编写了一个通用的Print()方法,用于打印不同类型的数组。

static void Main()
{
    Print(new double[]{ 1, 2, 3 });

    // Output: [ 1, 2, 3 ]
}

static void Print<T>(T[] array)
{
    int size = array.Length;
    if (size == 0)
        return;

    string str = "[ ";

    for (int i = 0; i < size; i++)
    {
        str += array[i].ToString();

        if (i < size - 1)
            str += ", ";
    }

    str += " ]";

    Console.WriteLine(str);
}

目前为止都很好用。然后我想打印一个数组的数组,比如double[][],尝试了以下代码:

static void Main()
{
    Print(new double[][]
    {
        new double[] { 1, 2 },
        new double[] { 3, 4 },
        new double[] { 5, 6 },
    });

    // Output: [ 1, 2 ]
    //         [ 3, 4 ]
    //         [ 5, 6 ]
}

static void Print<T>(T[] array)
{
    if (array.Length == 0)
        return;

    if (array[0].GetType().IsArray)
    {
        foreach (var element in array)
        {
            Print<T>(element);
        }
    }
    else
    {
        int size = array.Length;
        string str = "[ ";

        for (int i = 0; i < size; i++)
        {
            str += array[i].ToString();

            if (i < size - 1)
                str += ", ";
        }

        str += " ]";

        Console.WriteLine(str);
    }
}

我只是想检查一下array的元素是否再次是数组,如果是,我会为array的每个element再次调用函数Print。但是Print(element)不起作用,因为element是类型T而不是T[],我不知道如何告诉编译器在这种情况下T是一个数组。我该怎么做才能让它工作?

一个可能很重要的点 - 你所谓的数组数组实际上被称为不规则数组。C#支持两种(double[][]double[,])。你需要同时支持两种吗?还是你只处理数组数组(即不规则数组)?在这里查看更多信息:https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/jagged-arrays - Jamiec
我需要不规则数组,因为我在尝试使用Accord.Net和他们的SVM。而他们的方法大多以不规则数组作为参数。 - Alexander Moser
2个回答

1
你应该为你的Print方法提供两个重载版本 - 你可以自由地从2D版本中调用1D版本:
static void Print<T>(T[][] array)
{
     Console.WriteLine("Print 2D Array");
}
static void Print<T>(T[] array)
{
     Console.WriteLine("Print 1D Array");
}

实时示例:http://rextester.com/LYBUN44476


虽然这确实解决了问题,但它不如一个递归执行此操作的单个方法优雅。难道没有更好的方法吗? - Neil
@Neil - 这是一个观点问题,我认为这种方法更加优雅,因为2D版本只是通过调用1D版本进行循环。简单、明确、类型安全。工作完成! - Jamiec
是的,但这样我每次添加一个维度到我的数组中都必须编写一个额外的重载。有没有办法在数组中迭代任意数量的维度?这就是我尝试使用递归调用自身构建此方法的原因。 - Alexander Moser
@AlexanderMoser,我仍然认为你最好为每个额外的维度编写一个简单的重载方法(你真正会有多少个?!)。每个方法只需调用其前一个方法-请参见更新后的实时示例。 - Jamiec
这是一个无关紧要的问题,因为实际上你很可能永远不需要为二维数组使用多个重载。我同意。虽然我认为在C#中有一种优雅的方法可以实现这一点。 - Neil
这也是我发布这个问题的部分原因,因为我也找不到更好的解决方案。我想知道是否有办法让它按照我尝试的方式工作。但还是谢谢你的帮助 :) - Alexander Moser

1
你可以使用动态方式来实现它:
    void Main()
    {
        Print(new double[][]
        {
            new double[] { 1, 2 },
            new double[] { 3, 4 },
            new double[] { 5, 6 },
        });

        // Output: [ 1, 2 ]
        //         [ 3, 4 ]
        //         [ 5, 6 ]
    }

    static void Print(dynamic array)
    {
        if (array.Length == 0)
            return;

        if (array[0].GetType().IsArray)
        {
            foreach (var element in array)
            {
                Print(element);
            }
        }
        else
        {
            int size = array.Length;
            string str = "[ ";

            for (int i = 0; i < size; i++)
            {
                str += array[i].ToString();

                if (i < size - 1)
                    str += ", ";
            }

            str += " ]";

            Console.WriteLine(str);
        }
    }

如果你只想测试代码的一小部分 - 我建议使用 LinqPad,它具有 AnyType.Dump() 方法,而且你不需要实现任何东西 ;)

酷,我不知道动态类型。由于任何涉及动态类型的操作都将在运行时解决,所以是否存在任何主要缺点?如果过于频繁使用,我可以想象这可能很容易成为错误和崩溃的源头? - Alexander Moser
这方面有一个非常好的SOF问题:)https://dev59.com/Z2s05IYBdhLWcg3wDttn - Piotr
现在对于通用参数没有太多用处 - 但是很好的答案! - Jamiec
Jamiec - 你是对的。现在不需要泛型。我会更新答案并删除泛型。 - Piotr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接