문제

즉, 다음과 같은 작업을 수행할 수 있습니까?

for() {
    for {
       for {
       }
    }
}

N 번 빼고요?즉, 루프를 생성하는 메서드가 호출되면 일부 매개변수 N이 주어지고 메서드는 이러한 루프 중 N개를 서로 중첩하여 생성하게 됩니다.

물론, "쉬운" 또는 "일반적인" 방법이 있어야 한다는 생각입니다.나는 이미 매우 복잡한 아이디어를 가지고 있습니다.

도움이 되었습니까?

해결책

당신이보고 싶을 수도있는 것 같습니다 재귀.

다른 팁

jjnguy는 옳다. 재귀를 사용하면 가변적인 깊은 네버링을 동적으로 생성 할 수 있습니다. 그러나 조금 더 작업하지 않고 외부 레이어의 데이터에 액세스 할 수 없습니다. "인라인 네트워크"케이스 :

for (int i = lo; i < hi; ++i) {
    for (int j = lo; j < hi; ++j) {
        for (int k = lo; k < hi; ++k) {
            // do something **using i, j, and k**
        }
    }
}

변수를 유지합니다 i, j, 그리고 k 가장 안쪽의 몸이 사용하는 범위.

다음은 다음과 같은 빠른 해킹입니다.

public class NestedFor {

    public static interface IAction {
        public void act(int[] indices);
    }

    private final int lo;
    private final int hi;
    private final IAction action;

    public NestedFor(int lo, int hi, IAction action) {
        this.lo = lo;
        this.hi = hi;
        this.action = action;
    }

    public void nFor (int depth) {
        n_for (0, new int[0], depth);
    }

    private void n_for (int level, int[] indices, int maxLevel) {
        if (level == maxLevel) {
            action.act(indices);
        } else {
            int newLevel = level + 1;
            int[] newIndices = new int[newLevel];
            System.arraycopy(indices, 0, newIndices, 0, level);
            newIndices[level] = lo;
            while (newIndices[level] < hi) {
                n_for(newLevel, newIndices, maxLevel);
                ++newIndices[level];
            }
        }
    }
}

그만큼 IAction 인터페이스 act 방법.

이 예에서는 각 인스턴스입니다 NestedFor 반복 제한과 가장 안쪽 레벨에 의해 수행 할 동작을 갖는 생성자에 의해 구성됩니다. 의 매개 변수 nFor 메소드는 얼마나 깊이 둥지를 지정하는지 지정합니다.

다음은 샘플 사용량입니다.

public static void main(String[] args) {
    for (int i = 0; i < 4; ++i) {
        final int depth = i;
        System.out.println("Depth " + depth);
        IAction testAction = new IAction() {
            public void act(int[] indices) {
                System.out.print("Hello from level " + depth + ":");
                for (int i : indices) { System.out.print(" " + i); }
                System.out.println();
            }
        };
        NestedFor nf = new NestedFor(0, 3, testAction);
        nf.nFor(depth);
    }
}

실행에서 (부분) 출력 :

Depth 0
Hello from level 0:
Depth 1
Hello from level 1: 0
Hello from level 1: 1
Hello from level 1: 2
Depth 2
Hello from level 2: 0 0
Hello from level 2: 0 1
Hello from level 2: 0 2
Hello from level 2: 1 0
Hello from level 2: 1 1
Hello from level 2: 1 2
Hello from level 2: 2 0
Hello from level 2: 2 1
Hello from level 2: 2 2
Depth 3
Hello from level 3: 0 0 0
Hello from level 3: 0 0 1
Hello from level 3: 0 0 2
Hello from level 3: 0 1 0
...
Hello from level 3: 2 1 2
Hello from level 3: 2 2 0
Hello from level 3: 2 2 1
Hello from level 3: 2 2 2

당신이 정말로 하고 싶은 것이 무엇인지 설명하고 싶을 수도 있습니다.

외부인 경우 for 루프는 카운트를 제어하는 ​​것 외에는 아무것도 하지 않고 중첩됩니다. for 루프는 단순히 단일로 처리할 수 있는 개수로 반복하는 더 복잡한 방법입니다. for 고리.

예를 들어:

for (x = 0; x < 10; ++x) {
  for (y = 0; y < 5; ++y) {
    for (z = 0; z < 20; ++z) {
      DoSomething();
    }
  }
}

다음과 같습니다:

for (x = 0; x < 10*5*20; ++x) {
  DoSomething();
}

나는 실제로 다른 날 이것에 대해 생각하고 있었다.

아마도 완벽하지는 않지만 제가 요청하고 있다고 생각하는 것과 거의 가까운 예는 디렉토리 트리를 인쇄하는 것입니다.

public void printTree(directory) {
   for(files in directory) {
      print(file);
      if(file is directory) {
          printTree(file);
      }
   }
}

이런 식으로 당신은 서로 안에 둥지를 둔 루프의 스택으로 끝납니다.

2015 편집 : 이전의 약탈과 같은 헛된 것을 따라 나는 이것을 처리하기 위해 다음과 같은 패키지를 만들었습니다. https://github.com/beundead/nfor

사용법은 다음과 같습니다

public static void main(String... args) {
    NFor<Integer> nfor = NFor.of(Integer.class)
            .from(0, 0, 0)
            .by(1, 1, 1)
            .to(2, 2, 3);

    for (Integer[] indices : nfor) {
        System.out.println(java.util.Arrays.toString(indices));
    }
}

~를 야기하는

[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 1, 0]
[0, 1, 1]
[0, 1, 2]
[1, 0, 0]
[1, 0, 1]
[1, 0, 2]
[1, 1, 0]
[1, 1, 1]
[1, 1, 2]

또한 다른 조건을 지원합니다 lessThan. 사용되는 사용법 (함께 import static NFor.*;):

NFor<Integer> nfor = NFor.of(Integer.class)
        .from(-1, 3, 2)
        .by(1, -2, -1)
        .to(lessThanOrEqualTo(1), greaterThanOrEqualTo(-1), notEqualTo(0));

를 야기하는:

[-1, 3, 2]
[-1, 3, 1]
[-1, 1, 2]
[-1, 1, 1]
[-1, -1, 2]
[-1, -1, 1]
[0, 3, 2]
[0, 3, 1]
[0, 1, 2]
[0, 1, 1]
[0, -1, 2]
[0, -1, 1]
[1, 3, 2]
[1, 3, 1]
[1, 1, 2]
[1, 1, 1]
[1, -1, 2]
[1, -1, 1]

분명히 길이와 다른 클래스의 루프 (모든 박스형, 숫자 프리미티브)가 지원됩니다. 기본값 (지정되지 않은 경우)은 (0, ...)에서 (1, ...); 그러나 A ~ (...)를 지정해야합니다.

그만큼 NForTest 파일은 몇 가지 다른 방법을 사용해야합니다.

이 전제는 재귀를 사용하기보다는 단순히 턴마다 '지수'를 발전시키는 것입니다.

문제는 더 많은 사양이 필요합니다. 어쩌면 재귀는 당신을 도울 것이지만, 재귀는 거의 항상 반복의 대안이며 그 반대도 마찬가지입니다. 2 단계 중첩 루프가 필요에 충분할 수 있습니다. 해결하려는 문제를 알려주십시오.

중첩 루프의 핵심 아이디어는 다음과 같습니다. 곱셈.

Michael Burr의 답변을 확장하면 외부 for 루프는 카운트를 제어하는 ​​것 외에는 아무것도 하지 않고 중첩됩니다. for 루프 오버 n count는 단순히 단일 값으로 count의 곱을 반복하는 더 복잡한 방법입니다. for 고리.

이제 이 아이디어를 목록으로 확장해 보겠습니다.중첩 루프에서 세 개의 목록을 반복하는 경우 이는 단일 루프로 목록의 곱을 반복하는 더 복잡한 방법일 뿐입니다.그러면 세 목록의 곱을 어떻게 표현합니까?

첫째, 유형의 산물을 표현하는 방법이 필요하다.두 가지 유형의 제품 X 그리고 Y 다음과 같은 일반 유형으로 표현될 수 있습니다. P2<X, Y>.이는 두 가지 값으로 구성된 값일 뿐입니다. X, 다른 유형 Y.다음과 같습니다.

public abstract class P2<A, B> {
  public abstract A _p1();
  public abstract B _p2();
}

세 가지 유형의 제품에 대해 우리는 P3<A, B, C>, 분명한 세 번째 방법이 있습니다.그러면 세 개의 목록으로 구성된 제품은 제품 유형에 대해 목록 기능자를 배포하여 달성됩니다.그래서 제품은 List<X>, List<Y>, 그리고 List<Z> 단순히 List<P3<X, Y, Z>>.그런 다음 단일 루프를 사용하여 이 목록을 반복할 수 있습니다.

그만큼 기능적 자바 도서관에는 List 일급 함수와 제품 유형(P2, P3 등)을 사용하여 목록의 곱셈을 지원하는 유형입니다.라이브러리에도 포함되어 있습니다).

예를 들어:

for (String x : xs) {
   for (String y : ys) {
     for (String z : zs) {
       doSomething(x, y, z);
     }
   }
}

다음과 같습니다:

for (P3<String, String, String> p : xs.map(P.p3()).apply(ys).apply(zs)) {
   doSomething(p._1(), p._2(), p._3());
}

Functional Java를 사용하여 더 나아가 다음을 수행할 수 있습니다. doSomething 다음과 같이 일류.의 말을하자 doSomething 문자열을 반환합니다:

public static final F<P3<String, String, String>, String> doSomething =
  new F<P3<String, String, String>, String>() {
    public String f(final P3<String, String, String> p) {
      return doSomething(p._1(), p._2(), p._3());
    }
  };

그런 다음 for 루프를 완전히 제거하고 모든 응용 프로그램의 결과를 수집할 수 있습니다. doSomething:

List<String> s = xs.map(P.p3()).apply(ys).apply(zs).map(doSomething);

다음과 같은 일반적인 중첩 루프 구조를 가지고있는 경우 :

for(i0=0;i0<10;i0++)
    for(i1=0;i1<10;i1++)
        for(i2=0;i2<10;i2++)
            ....
                for(id=0;id<10;id++)
                    printf("%d%d%d...%d\n",i0,i1,i2,...id);

어디 i0,i1,i2,...,id 루프 변수입니다 d 중첩 루프의 깊이입니다.

동등한 재귀 솔루션 :

void nestedToRecursion(counters,level){
    if(level == d)
        computeOperation(counters,level);
    else
    {
        for (counters[level]=0;counters[level]<10;counters[level]++)
            nestedToRecursion(counters,level+1);
    }
}
void computeOperation(counters,level){
    for (i=0;i<level;i++)
        printf("%d",counters[i]);
    printf("\n");
}

카운터는 크기의 배열입니다 d, 해당 변수를 나타냅니다 i0,i1,i2,...id 각기 int counters[d].

nestedToRecursion(counters,0);

마찬가지로 재귀 초기화와 같은 다른 변수를 변환 할 수 있습니다. initial[d], ending[d].

Java 7에서 내가 생각해 낼 수있는 가장 깔끔한 일반적인 접근법은

// i[0] = 0..1  i[1]=0..3, i[2]=0..4
MultiForLoop.loop( new int[]{2,4,5}, new MultiForLoop.Callback() { 
    void act(int[] i) { 
        System.err.printf("%d %d %d\n", i[0], i[1], i[2] );
    }
}

또는 Java 8 :

// i[0] = 0..1  i[1]=0..3, i[2]=0..4
MultiForLoop.loop( new int[]{2,4,5}, 
   i -> { System.err.printf("%d %d %d\n", i[0], i[1], i[2]; } 
);

이를 지원하는 구현은 다음과 같습니다.

/**
 * Uses recursion to perform for-like loop.
 *  
 * Usage is 
 *  
 *    MultiForLoop.loop( new int[]{2,4,5}, new MultiForLoop.Callback() { 
 *        void act(int[] indices) { 
 *            System.err.printf("%d %d %d\n", indices[0], indices[1], indices[2] );
 *        }
 *    }
 *  
 * It only does 0 - (n-1) in each direction, no step or start 
 * options, though they could be added relatively trivially.
 */
public class MultiForLoop {

    public static interface Callback {
        void act(int[] indices);
    }

    static void loop(int[] ns, Callback cb) {
        int[] cur = new int[ns.length];
        loop(ns, cb, 0, cur);
    }

    private static void loop(int[] ns, Callback cb, int depth, int[] cur) {
        if(depth==ns.length) {
            cb.act(cur);
            return;
        }

        for(int j = 0; j<ns[depth] ; ++j ) {
            cur[depth]=j;
            loop(ns,cb, depth+1, cur);
        }
    }
}
String fors(int n){
StringBuilder bldr = new StringBuilder();
for(int i = 0; i < n; i++){
    for(int j = 0; j < i; j++){
        bldr.append('\t');
    }
    bldr.append("for() {\n");
}
for(int i = n-1; i >= 0; i--){
    for(int j = 0; j < i; j++){
        bldr.append('\t');
    }
    bldr.append("}\n");
}
return bldr.toString();
}

멋진 중첩 for-loop 골격을 만듭니다 ;-) 완전히 심각하지 않으며 재귀 솔루션이 더 우아했을 것임을 알고 있습니다.

public void recursiveFor(Deque<Integer> indices, int[] ranges, int n) {

    if (n != 0) {

       for (int i = 0; i < ranges[n-1]; i++) {

          indices.push(i);
          recursiveFor(indices, ranges, n-1);
          indices.pop();
       }
    }

    else {

       // inner most loop body, access to the index values thru indices
       System.out.println(indices);
    }
}

샘플 전화 :

int[] ranges = {2, 2, 2};

recursiveFor(new ArrayDeque<Integer>(), ranges, ranges.length);

질문에 처음으로 대답했지만`의이 정보를 공유해야한다고 생각했습니다.

for (x = 0; x < base; ++x) {
  for (y = 0; y < loop; ++y) {
      DoSomething();
  }
}

동등합니다

for (x = 0; x < base*loop; ++x){
    DoSomething();
}

따라서 N 수의 둥지를 원한다면 사이의 분할을 사용하여 작성할 수 있습니다. base 그리고 loop 따라서 이것만큼 간단하게 보일 수 있습니다.

char[] numbs = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
     public void printer(int base, int loop){
       for (int i = 0; i < pow(base, loop); i++){
         int remain = i;
         for (int j = loop-1; j >= 0; j--){
           int digit = remain/int(pow(base, j));
           print(numbs[digit]);
           remain -= digit*pow(base, j);
         }
         println();
       }
     }

그래서 당신이 입력했다면 printer(10, 2); 인쇄 할 것입니다.

00
01
02
03
04
...
97
98
99

이것은 저에게 정말 친절하게 작동했습니다. 나는 일부 대안 중에서 선택해야했는데, 근거리 경로에 저장된 대안 중에서 선택해야했고 기본 아이디어는 다음 선택을 구성하려고했고, 한 차원 / 구성 요소에 "오버플로"가 있었을 때, 당신은 단지 당신은 단지 당신은 단지 당신입니다. 해당 차원을 다시 구분하고 다음 차원에 추가하십시오.

public boolean isValidAlternativeSelection (int[] alternativesSelected) {
    boolean allOK = true;
    int nPaths= myAlternativePaths.size();
    for (int i=0; i<nPaths; i++) {
        allOK=allOK & (alternativesSelected[i]<myAlternativePaths.get(i).myAlternativeRoutes.size());
    }
    return allOK;
}


public boolean getNextValidAlternativeSelection (int[] alternativesSelected) {
    boolean allOK = true;
    int nPaths= myAlternativePaths.size();
    alternativesSelected[0]=alternativesSelected[0]+1;
    for (int i=0; i<nPaths; i++) {
        if (alternativesSelected[i]>=myAlternativePaths.get(i).myAlternativeRoutes.size()) {
            alternativesSelected[i]=0;
            if(i<nPaths-1) {
                alternativesSelected[i+1]=alternativesSelected[i+1]+1;
            } else {
                allOK = false;
            }
        }
 //       allOK=allOK & (alternativesSelected[i]<myAlternativePaths.get(i).myAlternativeRoutes.size());
    }
    return allOK;
}

간결함을 위해 나는 여기에 내 코드를 넣고있다.

void variDepth(int depth, int n, int i) {
    cout<<"\n d = "<<depth<<" i = "<<i;
    if(!--depth) return;
    for(int i = 0;i<n;++i){
        variDepth(depth,n,i);
    }
}
void testVariDeapth()
{   variDeapth(3, 2,0);
}

산출

 d = 3 i = 0
 d = 2 i = 0
 d = 1 i = 0
 d = 1 i = 1
 d = 2 i = 1
 d = 1 i = 0
 d = 1 i = 1
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top