任意维度的数组作为方法参数

8

我有一个简单的转换方法,可以将一个boolean类型的数组转换为int类型:

public static int[] convert1dToInt (boolean[] x) {

    int la = x.length;
    int[] y = new int[la];

    for (int a = 0; a < la; a++) {
        if (x[a]) {
            y[a] = 1;
        } else {
            y[a] = 0;
        }
    }

    return y;
}

现在我有一个用于二维数组的相同方法:

public static int[][] convert2dToInt (boolean[][] x) {

    int la = x.length;
    int lb = x[0].length;
    int[][] y = new int[la][lb];

    for (int a = 0; a < la; a++) {
        for (int b = 0; b < lb; b++) {
            if (x[a][b]) {
                y[a][b] = 1;
            } else {
                y[a][b] = 0;
            }
        }
    }

    return y;
}

如何在不手动编写所有方法的情况下将这些方法推广到任意维度的数组?

3
不要这么做。你为什么认为 Object 类有 wait()wait(long) 方法?重载这些方法,不要使用同一个方法来实现两个功能。 - TheLostMind
不太确定有没有办法做到这一点...我猜可能会有一些使用反射的技巧,但那将会非常混乱。 - MightyPork
1
我只能想象如何使用递归算法来实现。它需要一个 Object[] 作为参数,并检查 Object 是否由 arrayBoolean 组成。如果是 Boolean,则递归循环结束。如果是 Array,则我们在 Object 上调用递归函数。我表述清楚了吗?我会尝试发布一个答案,但我会先检查它是否有效。 - Kabulan0lak
你的数据从哪里来?使用列表可能比数组更容易。 - Leon
3个回答

2
您可以对传递的参数类型使用条件递归,并在维度为1时使用convert1dToInt,然后将结果收集到一个对象中,在给定的上下文中,您将被迫只传递一个Object类型的对象并返回一个对象,然后您需要进行强制转换。这里是一个小代码,它展示了仅打印数组元素值的递归函数的想法:
public static void convertDimN(Object o) {

    if (o.getClass().isArray() && Array.get(o, 0).getClass().isArray()) {
        // is o a two dimentional array
     for (int i = 0; i < Array.getLength(o); i++) {
            convertDimN(Array.get(o, i));
        }
    } else
        for (int i = 0; i < Array.getLength(o); i++) {
            System.out.println(Array.get(o, i));
        }
}

2

这是可能的,但反射和递归都是不可避免的:

import java.lang.reflect.Array;

public class ArrayTransfer {

    private static int getArrayDimension(Object array) {
        Class<?> clazz = array.getClass();
        int dimension = 0;
        while (clazz.isArray()) {
            clazz = clazz.getComponentType();
            dimension += 1;
        }

        if (clazz != boolean.class) {
            throw new IllegalArgumentException("Base array type not boolean");
        }

        return dimension;
    }

    // Transfers a boolean array of the specified dimension into an int
    // array of the same dimension.
    private static Object transferToIntArray(Object booleanArray, int dimension) {
        if (booleanArray == null) {
            return null;
        }

        // Determine the component type of the new array.
        Class<?> componentType;
        if (dimension == 1) {
            componentType = int.class;
        } else {
            // We have a multidimensional array; the dimension of the component
            // type is one less than the overall dimension.  Creating the class
            // of an array of an unknown dimension is slightly tricky: we do
            // this by creating a 0 x 0 x ... x 0 array (with dimension - 1
            // zeros) and then getting the class of this array.  Handily for us,
            // int arrays are initialised to all zero, so we can create one and
            // use it straight away.
            int[] allZeroDimensions = new int[dimension - 1];
            componentType = Array.newInstance(int.class, allZeroDimensions).getClass();
        }

        // Create the new array.
        int length = Array.getLength(booleanArray);
        Object newArray = Array.newInstance(componentType, length);

        // Transfer the elements, recursively if necessary.
        for (int i = 0; i < length; ++i) {
            if (dimension == 1) {
                Boolean value = (Boolean)Array.get(booleanArray, i);
                Array.set(newArray, i, (value.booleanValue()) ? 1 : 0);
            }
            else {
                Object oldChildArray = Array.get(booleanArray, i);
                Object newChildArray = transferToIntArray(oldChildArray, dimension - 1);
                Array.set(newArray, i, newChildArray);
            }
        }

        return newArray;
    }

    // Transfers a boolean array of some dimension into an int
    // array of the same dimension.
    public static Object transferToIntArray(Object booleanArray) {
        if (booleanArray == null) {
            return null;
        }

        int dimension = getArrayDimension(booleanArray);
        return transferToIntArray(booleanArray, dimension);
    }
}

这应该适用于任何维度的数组,最多可达255个——我用5个维度进行了快速测试,它似乎可以正常工作。它还应该适用于‘不规则’数组和null值。

要使用它,请调用ArrayTransfer.transferToIntArray(...),并将您的boolean数组作为参数传入,它将返回相应的int数组。当然,您需要将此方法的返回值强制转换为相关的int数组类型。

这方面肯定有改进的空间。特别是,如果保留各种数组类的某些缓存,而不必只是为了获取它们的类而实例化空数组,则会更好。


1
这将是你的第一个方法:

    public static int[] convert1dToInt (boolean[] x) {

        //int la = x.length; is useless since you are accessing an object member and not a method

     int[] y = new int[x.length];

        for (int a = 0; a < x.length; a++) {
          y[a] = x[a] ? 1 :0;
    }
    return y;
}

简单地重复使用你的代码 - 我没有太多时间,因为现在是我的午餐时间,所以我不知道是否全部正确,但方法应该是适合的:

public static int[][] convert2dToInt (boolean[][] x)  {

         int[][] y = new int[x.length][];

            for (int a = 0; a < x.length; a++) {
              y[a] = convert1dToInt (x[a]) ;
        }
        return y;
    }

好的,这个解决方案并不是问题的答案,因为我没有准确地阅读被问到的内容。对此我很抱歉。据我所知,只要你使用原始数据类型,就不可能有一种通用的方法。这是因为你不能将int[]作为int[]的成员添加。因此,你应该使用Object[]、Boolean[]和Integer[],但我不知道你想如何处理它们。我认为写这样一个方法是没有意义的,因为当你能够转换这样的数据结构时,你如何访问目标。由于你不知道你的数组将有多少维,你无法编写通用方法来访问成员。我会尝试写一个解决方案,因为我想知道是否还有其他可能的解决方案。我的理解是,问题是是否可能而不是是否合理?

我认为如果你告诉我们你想要使用这段代码的用例,我们可以找到最佳解决方案。正如我所说,当我以后有更多时间时,我会尝试找到另一种解决方案。


这实际上不是 Op 想要做的。 - Ruchira Gayan Ranaweera
哦,抱歉,好的,我不会在午餐时间回答问题了,我不会... ;) 抱歉,我应该更仔细地阅读。 - wstein
我认为这是使用Java OP可以做到的最好的。 - A4L

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