我有一个关于数字生成的新问题,问题从这段代码开始:
for(int i = a1; i<n;i+=s1){
for(int j = a2; j<m;j+=s2){
for(int k = a3; k<f;k+=s3){
....
doCalculation(new double[]{i,j,k})
正如你所看到的,我有一些嵌套的for循环,其数字不固定,而且范围是固定的。我想知道是否有一个函数可以将上面的代码转换成类似的东西:
for(int i = 0; i<n*m*f*...;i++){
doCalculation(evaluateParameters(i))
布鲁斯的回答很好地解决了
doCalculations(0, new int[3], new int[]{1,2,3}, new int[]{7,5,5}, new int[]{2,1,3});
static void doCalculations(int current, int[] params, int[] starts, int[]
limits, int[] incrementers) {
if(current == limits.length) return;
if(current==0){ // initialize with default values
params = new int[]{1,2,3};
}
for(int i = starts[current]; i <= limits[current]; i += incrementers[current]) {
int tmp = params[current];
params[current] = i;
System.out.println(Arrays.toString(params));
doCalculations(current + 1, params, starts, limits, incrementers);
params[current] = tmp;
}
}
但仍然无效,请参阅输出
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 3, 3]
[1, 3, 3]
[1, 4, 3]
[1, 4, 3]
[1, 5, 3]
[1, 5, 3]
[3, 2, 3]
[3, 2, 3]
[3, 2, 3]
[3, 3, 3]
[3, 3, 3]
[3, 4, 3]
[3, 4, 3]
[3, 5, 3]
[3, 5, 3]
...
编辑2:算法的面向对象版本:
public class PriceEntity {
static void doCalculations(List<SingleParameter> parameters) {
doCalculations(0, null, parameters);
}
static void doCalculations(int current, int[] params, List<SingleParameter> parameters) {
if(current == parameters.size()) return;
if(params==null){ // initialize with default values
params = new int[parameters.size()];
for (int i = 0; i < parameters.size(); i++) params[i] = parameters.get(i).getStart();
System.out.println(Arrays.toString(params));
doCalculations(current, params, parameters);
return;
}
//System.out.println("Current is: " + current);
SingleParameter parameterToIncrement = parameters.get(current);
for(int i = parameterToIncrement.getStart() i <= parameterToIncrement.getStop(); i += parameterToIncrement.getIncrement()) {
int tmp = params[current];
params[current] = i;
System.out.println(Arrays.toString(params));
doCalculations(current + 1, params, parameters);
params[current] = tmp;
}
}
public static void main(String[] args) {
ArrayList <SingleParameter> parameters = new ArrayList<>();
parameters.add(new SingleParameter(1,5,1)); // 5
parameters.add(new SingleParameter(2,6,2)); // 3
parameters.add(new SingleParameter(2,5,3)); // 1
parameters.add(new SingleParameter(4,12,4)); // 3
doCalculations(parameters);
}
}
@Data @NoArgsConstructor @AllArgsConstructor public class SingleParameter {
private int start, stop, increment;
}
但仍然无效
[1, 2, 2, 4]
[1, 2, 2, 4]
[1, 2, 2, 4]
[1, 2, 2, 4]
[1, 2, 2, 4]
[1, 2, 2, 8]
[1, 2, 2, 12]
[1, 2, 5, 4]
[1, 2, 5, 4]
[1, 2, 5, 8]
[1, 2, 5, 12]
[1, 4, 2, 4]
[1, 4, 2, 4]
[1, 4, 2, 4]
[1, 4, 2, 8]
[1, 4, 2, 12]
[1, 4, 5, 4]
[1, 4, 5, 4]
[1, 4, 5, 8]
[1, 4, 5, 12]
[1, 6, 2, 4]
[1, 6, 2, 4]
[1, 6, 2, 4]
[1, 6, 2, 8]
[1, 6, 2, 12]
...... 140 records
答案 0 :(得分:2)
如果循环计数未修复,则应使用递归。它可以被调用到任何深度。
void calc(List<Integer> params, int loopsCount, int[] loopLimits)
int limit = loopLimits[loopsCount];
for (int i = 0; i < limit; i++) {
params.add(i);
if (loopsCount == 0) doCalculation(params)
else calc(params, loopsCount - 1, loopLimits);
params.removeLast();
}
}
当然,你可以在一个for循环中通过一个限制数组limits
,使其所有成员相乘,并运行一个循环到最终产品。但是你会失去每个索引的信息,所以你需要计算它并存储在一个临时数组中,例如es
int product = limits[0] * limits[1] * ... * limits[n];
...
int[] indexes = new int[n];
for (i = 0; i < product; i++) {
doCalculation(indexes);
increaseIndex = 0;
while(true) {
if (indexes[increaseIndex]++ == limits[increaseIndex])
indexes[increaseIndex++] = 0;
else break;
}
}
但这是不可理解的,也不清楚。但是,可能比递归更快。
答案 1 :(得分:2)
Java for
循环不支持在多维结构上循环。
这是一个递归方法,它将模拟n嵌套的for
循环。
请注意,params是启动的克隆,因为否则对doCalculation()
的第一次调用将传递一个大部分未初始化的数组,在本例中为[4, 0, 0]
,其中4
是第一个元素在starts
。
int[] starts = new int[]{4, 5, 6};
int[] limits = new int[]{7, 8, 10};
int[] incrementers = new int[]{1, 2, 3}; // elements cannot be <= 0
int[] params = starts.clone(); // must be a clone of starts
doCalculations(starts, limits, incrementers, params, 0);
void doCalculations(int[] starts, int[] limits, int[] incrementers, int[] params, int current) {
if(current == limits.length) {
return;
}
for(int i = starts[current]; i < limits[current]; i += incrementers[current]) {
params[current] = i;
if(current == params.length - 1) {
doCalculation(params);
}
doCalculations(starts, limits, incrementers, params, current + 1);
}
}