通过排列的动态循环量

时间:2014-07-24 21:39:17

标签: java arrays list recursion

我有一个动态访问不同方法的程序,每个方法都有不同的参数。我需要找到一种方法来通过这些参数的数千种不同排列进行置换,我不确定如何动态地遍历这些排列。

例如,对于具有两个参数的函数,我可以迭代这样的排列:

public static void main(String[] args) {
    List<Object[]> params = new ArrayList();
    params.add(new Integer[]{1,2,3});
    params.add(new Boolean[]{false,true});

    runCalculation("function1",params);
}

public void runCalculation(String functionName, List<Object> parameters){

    for(Object i : parameters.get(0)){
        for(Object j : parameters.get(1)){
            //Do reflection function call with (i,j) as parameters
        }
    }
}

但是如果我想要运行下一个函数,则使用3个参数,这将不再遍历所有排列。如何使用动态数量的for循环来正确处理包含参数值的数组列表?我认为递归是实现这样的事情的唯一方法,但我仍然在努力想出一个正确的解决方案,这将正确地为每个函数提供动态数量的参数,然后为这些参数提供不同的类型。

5 个答案:

答案 0 :(得分:1)

public void runCalculation(String functionName, List<Object> ... parameters){

    for(List<Object> list : parameters)
    {
         //Do reflection function call with obj as parameter
    }
}

它的名为varargs,也尝试使用enhanced for - 它更容易使用且开销很小

答案 1 :(得分:0)

如果我不理解这个问题,我很抱歉,但是嵌套for循环呢?

for(int i = 0; i < params.size(); i++)
{
  for(int j = 0; j < params.get(i).size(); j++)
  {
  }
}

这会有用吗?

编辑: 我想出了你正在寻找的算法,递归解决方案是:

public static String recursive(List<Object[]> params)
{
  String result = "";
  if(Params.isEmpty())
    return result;
  Object[] objects = params.remove(0);
  for(Object i : objects)
  {
    result += i.toString();
    List<Object[]> newParams = new ArrayList<>(newParams);
    result += recursive(newParams);
  }
  return result;
}

答案 2 :(得分:0)

我认为你在这里尝试的是反思。您只需阅读API并使用适当的方法即可。请注意,您 需要知道要在哪个类上调用方法名称。 Java不会为你查看所有类中的所有方法。

   public void runCalculation(String functionName, List<Object> parameters)
           throws NoSuchMethodException
   {
      Class<?>[] typeSignature = new Class<?>[ parameters.size() ];
      for( int i = 0; i < parameters.size(); i++ ) {
         typeSignature[i] = parameters.get( i ).getClass();
      }
      Class<?> type = this.getClass(); // substitute with desired class
      Method m = type.getMethod(functionName, typeSignature);
      // do stuff with 'm' here (like invoke it)

   }

答案 3 :(得分:0)

这是我的解决方案(我不知道数组不会实现Iterable,而且我现在懒得改变它,因为它基于交互器):< / p>

public static void print(Object a, Object b, Object c) {
    System.out.format("%s, %s, %s\n", a, b, c);
}

public static void runCalculation(Method m, Object instance, List<Iterable<?>> argList)
        throws Exception {
    int argc = argList.size(); //ARG Count
    int depth = 0;
    Stack<Iterator<?>> iteratorStack = new Stack<>();
    Object[] args = new Object[argc]; //call with these args

    boolean fromTop = true; //to know where we come from

    while (depth > -1) {
        if (fromTop && depth == argc) {
            m.invoke(instance, args);
            depth--;
            fromTop = false;
        } else if(fromTop) {
            iteratorStack.push(argList.get(depth).iterator());
            fromTop = false;
        } else if (iteratorStack.peek().hasNext()) {
            args[depth] = iteratorStack.peek().next();
            depth++;
            fromTop = true;
        } else {
            iteratorStack.pop();
            depth--;
            fromTop = false;
        }
    }
}

public static void main(String[] args) throws Exception {
    List<Iterable<?>> list = new ArrayList<>();
    list.add(Arrays.asList("one", "two"));
    list.add(Arrays.asList(3, 4));
    list.add(Arrays.asList(true, false));

    Method m = NaryProduct.class.getMethod("print", Object.class, Object.class, Object.class);
    runCalculation(m, null, list);
}

输出:

one, 3, true
one, 3, false
one, 4, true
one, 4, false
two, 3, true
two, 3, false
two, 4, true
two, 4, false

答案 4 :(得分:0)

以下是如何在C中执行类似的操作:应该很容易转换为Java。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

runCalculation( char * functionName, char * parameters, int numParams )
{
    int size = strlen(parameters);  // number of parameters to choose from
    int i, j;
    int indices[numParams];

    for (i=0; i < numParams; ++i)
        // initialise indices
        indices[i] = i;

    while (1) {
        // output parameters
        for (i=0; i < numParams; ++i)
            printf("%c", parameters[indices[i]]);
        printf("\n");

        // now advance j'th parameter
        j = numParams - 1;
        while(1) {
            indices[j]++;
            if (indices[j] < size - (numParams-1-j))
                // found a combination that 'works'
                break;
            // can't create a new combination with current j, so try new one
            --j;
            if (j < 0)
                return;
        }
        // reset everything after indices[j]: they will all be consecutive
        for (i=j+1; i < size; ++i)
            indices[i] = indices[i-1] + 1;

    }

}


main( int argc, char ** argv) {
    if (argc != 3) {
        printf("need two arguments (string to permute, # of combo elements): bye\n");
        exit(1);
    }
    runCalculation( "testFunction", argv[1], atoi(argv[2]) );

}

使用输入&#34; abcdef&#34;运行时的输出和4:

abcd
abce
abcf
abde
abdf
abef
acde
acdf
acef
adef
bcde
bcdf
bcef
bdef
cdef

将代码保存到您的系统中,编译它,尝试各种测试用例,一旦您确信这是您需要的,那么请告诉我Java的写法。我才知道。谢谢。