简体   繁体   English

任意维数组作为方法参数

[英]Array of arbitrary dimension as method parameter

I have a simple converter method for an array from boolean to int : 我有一个简单的转换方法,用于从booleanint的数组:

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

Now I have the same method for 2-dimensional arrays: 现在我对二维数组有相同的方法:

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

How can I generalize those methods for arrays of arbitrary dimension without writing all the methods by hand? 如何在不编写所有方法的情况下,将这些方法推广到任意维度的数组?

This is possible, but reflection and recursion are both inevitable: 这是可能的,但反射和递归都是不可避免的:

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);
    }
}

This should work with any number of dimensions up to 255 - I gave it a quick test with 5 and it seemed to work. 这应该适用于任何数量的高达255的维度 - 我用5快速测试它似乎工作。 It should also work with 'jagged' arrays, and with null s. 它也应该与'锯齿'数组一起使用,并使用null s。

To use it, call ArrayTransfer.transferToIntArray(...) with your boolean array, and it will return the corresponding int array. 要使用它,请使用boolean数组调用ArrayTransfer.transferToIntArray(...) ,它将返回相应的int数组。 You will of course need to cast the return value of this method to the relevant int array type. 您当然需要将此方法的返回值强制转换为相关的int数组类型。

There's certainly scope for improving this. 这当然有改进的余地。 In particular, it would be nicer if some cache of the various array classes was kept, rather than having to instantiate empty arrays just to get their class. 特别是,如果保留各种数组类的某些高速缓存,而不是仅仅为了获取它们的类而必须实例化空数组,那就更好了。

You can use a conditional recursivity on the type of the passed parameter and you use convert1dToInt for the dimension one , then you collect the result in one object, in the given context you will be forced to pass just an object of type Object and return an Object then you cast it , here is a small code that present idea of the recursive function that just print the value of the elements in the array : 您可以对传递的参数的类型使用条件递归,并将convert1dToInt用于维度1,然后在一个对象中收集结果,在给定的上下文中,您将被强制仅传递Object类型的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));
        }
}

This would be your first method: 这将是你的第一个方法:

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

Simply reuse your code - I had not much time since it is my lunch break so I don#t know if all is correct but the way should fit: 只需重复使用您的代码 - 我没有太多时间,因为这是我的午休时间,所以我不知道是否一切正确,但方式应该适合:

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

Ok, this solution was not the answer for the problem since I did not read exactly what has been asked. 好吧,这个解决方案不是问题的答案,因为我没有准确地读出所询问的内容。 Sorry for that. 对不起。 As far as I know a generalized method is not possible as long as you are working with primitive datatypes. 据我所知,只要您使用原始数据类型,就不可能使用通用方法。 This is because you can't add an int[] as a member for an int[]. 这是因为您不能将int []添加为int []的成员。 So you should then work with Object[], Boolean[] and Integer[] but I don't know how you want to work with that. 所以你应该使用Object [],Boolean []和Integer [],但我不知道你想如何使用它。 I don't think it is sensible to write such a method because when you are able to convert such a data-structure how do you want the targets to be accessed. 我不认为编写这样的方法是明智的,因为当你能够转换这样的数据结构时,你希望如何访问目标。 Since you do not know how many dimensions your array will have you can't write generic methods to access the members. 由于您不知道数组将具有多少维度,因此无法编写访问成员的通用方法。 I will try to write a solution for that since I want to know if I find an other possible solution. 我会尝试为此编写解决方案,因为我想知道我是否找到了其他可能的解决方案。 Am I right that the question is, if it is possible and not if it is reasonable? 我是对的,问题是,如果可能而不是合理的话?

I think we can find the best solution for that if you tell us the usecase you want to have this code for. 如果您告诉我们您想要使用此代码的用例,我想我们可以找到最佳解决方案。 As I said, when I have more time later on I'll try to find another solution. 正如我所说,当我有更多时间后,我会尝试寻找另一种解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM