RecursiveIteratorIterator는 PHP에서 어떻게 작동합니까?


88

어떻게 RecursiveIteratorIterator작동합니까?

PHP 매뉴얼에는 많이 문서화되거나 설명되어 있지 않습니다. IteratorIterator과 의 차이점은 무엇입니까 RecursiveIteratorIterator?


2
php.net/manual/en/recursiveiteratoriterator.construct.php에 예제가 있고 php.net/manual/en/class.iteratoriterator.php 에 소개도 있습니다-정확히 이해하는 데 어려움이있는 것을 지적 해 주 시겠습니까 ? . 이해하기 쉽도록 매뉴얼에는 무엇을 포함해야합니까?
Gordon

1
어떻게 RecursiveIteratorIterator작동 하는지 묻는다면 이미 어떻게 IteratorIterator작동 하는지 이해 했습니까? 기본적으로 동일하고 둘이 소비하는 인터페이스 만 다릅니다. 그리고 몇 가지 예제에 더 관심이 있습니까? 아니면 기본 C 코드 구현의 차이점을보고 싶습니까?
hakre

@Gordon 나는 어떻게 단일 foreach 루프가 트리 구조의 모든 요소를 ​​순회 할 수 있는지 확신하지
못했습니다

@hakra 나는 지금 모든 내장 인터페이스와 spl 인터페이스 및 반복기 구현을 연구하려고 노력하고 있습니다.
varuog 2012 년

@hakre 둘 다 실제로 매우 다릅니다. IteratorIterator지도 IteratorIteratorAggregateIterator어디에 REcusiveIteratorIterator사용됩니다 recusivly 트래버스합니다RecursiveIterator
아담

답변:


251

RecursiveIteratorIterator구체적인 Iterator구현 트리 순회 입니다. 이를 통해 프로그래머는 RecursiveIterator인터페이스 를 구현하는 컨테이너 객체를 순회 할 수 있습니다. 반복기 의 일반 원칙, 유형, 의미론 및 패턴은 Wikipedia의 Iterator를 참조하세요 .

차이에 IteratorIterator있는 콘크리트입니다 Iterator선형 순서 (기본적으로 모든 종류의 수용 구현하는 객체 통과 Traversable생성자에서이)는이 RecursiveIteratorIterator의 모든 노드에 걸쳐 반복 할 수 있습니다 주문 트리 객체와 생성자는 걸립니다 RecursiveIterator.

간단히 말해서 : RecursiveIteratorIterator트리 IteratorIterator를 반복 할 수 있고 목록을 반복 할 수 있습니다. 곧 아래의 몇 가지 코드 예제를 통해이를 보여 드리겠습니다.

기술적으로 이것은 모든 노드의 자식 (있는 경우)을 순회하여 선형성을 벗어나 작동합니다. 이것은 정의에 따라 노드의 모든 자식이 다시 RecursiveIterator. Iterator그런 다음 최상위 수준 RecursiveIterator은 깊이별로 다른 s 를 내부적으로 스택하고 Iterator순회 를 위해 현재 활성 하위에 대한 포인터를 유지합니다 .

이를 통해 트리의 모든 노드를 방문 할 수 있습니다.

기본 원칙은 with와 동일합니다 IteratorIterator. 인터페이스는 반복 유형을 지정하고 기본 반복기 클래스는 이러한 의미를 구현합니다. 아래의 예와 비교해 보면, 선형 루핑의 경우 foreach일반적으로 새로 정의 할 필요가없는 한 구현 세부 사항에 대해 많이 생각하지 않습니다 Iterator(예 : 일부 구체적인 유형 자체가 구현하지 않는 경우 Traversable).

재귀 탐색을 위해 - 당신이 사용하지 않는 한 사전 정의 된 Traversal이미 재귀 탐색 반복 가지고 - 당신이 일반적으로 필요한 기존의 인스턴스를 RecursiveIteratorIterator반복하거나 쓰기 재귀 탐색 반복 A는 그 Traversable탐색 반복과의이 유형을 가지고 자신의 foreach.

팁 : 하나 또는 다른 하나를 직접 구현하지 않았을 수 있으므로 차이점에 대한 실제 경험을 위해 수행 할 가치가있을 수 있습니다. 답변 끝에 DIY 제안이 있습니다.

요약하자면 기술적 차이점 :

  • 하지만 IteratorIterator어떤 걸리는 Traversable선형 탐색을 위해, RecursiveIteratorIterator더 구체적인 필요 RecursiveIterator트리를 통해 루프를.
  • 여기서 IteratorIterator주요 노출 Iterator비아를 getInnerIerator(), RecursiveIteratorIterator현재의 액티브 서브를 제공 Iterator해당 방법을 통해.
  • 하지만 IteratorIterator완전히 부모 나 아이 같은 것을 인식하지, RecursiveIteratorIterator뿐만 아니라 얻고 이송 어린이하는 방법을 알고있다.
  • IteratorIterator반복기 스택이 필요하지 않으며 RecursiveIteratorIterator이러한 스택이 있으며 활성 하위 반복기를 알고 있습니다.
  • 어디 IteratorIterator선형성과 선택의 여지로 인해 수주가 RecursiveIteratorIterator더 탐색하고 각 노드 당 결정하는 요구에 대한 선택의 여지가을 (를 통해 결정 모드 당RecursiveIteratorIterator ).
  • RecursiveIteratorIterator보다 많은 메서드가 IteratorIterator있습니다.

요약하면 : RecursiveIterator는 자체 반복자 (즉,)에서 작동하는 구체적인 반복 유형 (트리를 반복)입니다 RecursiveIterator. 이는와 동일한 기본 원칙 IteratorIerator이지만 반복 유형이 다릅니다 (선형 순서).

이상적으로는 자신 만의 세트를 만들 수도 있습니다. 필요한 유일한 것은 반복자 TraversableIterator또는을 통해 가능한 것을 구현 하는 것입니다 IteratorAggregate. 그런 다음 foreach. 예를 들어, 컨테이너 객체에 대한 반복 인터페이스와 함께 일종의 삼항 트리 순회 재귀 반복 객체.


그다지 추상적이지 않은 실제 사례를 살펴 보겠습니다. 인터페이스, 구체적인 반복기, 컨테이너 객체 및 반복 의미론 사이에서 이것은 그렇게 나쁜 생각이 아닐 수도 있습니다.

디렉토리 목록을 예로 들어 보겠습니다. 디스크에 다음 파일 및 디렉토리 트리가 있다고 가정하십시오.

디렉토리 트리

선형 순서의 반복기는 최상위 폴더 및 파일 (단일 디렉토리 목록)을 순회하는 반면, 반복 반복기는 하위 폴더도 탐색하고 모든 폴더 및 파일 (하위 디렉토리 목록이있는 디렉토리 목록)을 나열합니다.

Non-Recursive        Recursive
=============        =========

   [tree]            [tree]
    ├ dirA            ├ dirA
    └ fileA           │ ├ dirB
                      │ │ └ fileD
                      │ ├ fileB
                      │ └ fileC
                      └ fileA

IteratorIterator디렉토리 트리를 순회 할 때 재귀가없는 것과 쉽게 비교할 수 있습니다 . 그리고 RecursiveIteratorIterator재귀 목록에서 볼 수 있듯이 트리로 이동할 수 있습니다.

처음에는이 를 반복 할 수 DirectoryIterator있는 구현 Traversable을 가진 매우 기본적인 예제 :foreach

$path = 'tree';
$dir  = new DirectoryIterator($path);

echo "[$path]\n";
foreach ($dir as $file) {
    echo " ├ $file\n";
}

위의 디렉토리 구조에 대한 예제 출력은 다음과 같습니다.

[tree]
 ├ .
 ├ ..
 ├ dirA
 ├ fileA

보시다시피 이것은 아직 IteratorIterator또는 RecursiveIteratorIterator. 대신 인터페이스에서 foreach작동하는 것만 사용 합니다 Traversable.

foreach기본적으로 선형 순서라는 반복 유형 만 알고 있기 때문에 반복 유형을 명시 적으로 지정할 수 있습니다. 언뜻보기에는 너무 장황 해 보일 수 있지만 데모 목적으로 (그리고 RecursiveIteratorIterator나중에 더 잘 보이게 IteratorIterator하기 위해) 디렉토리 목록에 대한 반복 유형을 명시 적으로 지정하여 선형 반복 유형을 지정할 수 있습니다 .

$files = new IteratorIterator($dir);

echo "[$path]\n";
foreach ($files as $file) {
    echo " ├ $file\n";
}

이 예는 거의 차이 즉, 첫 번째와 동일한 $files지금이다 IteratorIterator위한 반복의 유형 Traversable $dir:

$files = new IteratorIterator($dir);

평소와 같이 반복 작업은 다음에 의해 수행됩니다 foreach.

foreach ($files as $file) {

출력은 정확히 동일합니다. 그래서 무엇이 다른가요? 내에서 사용되는 개체는 다릅니다 foreach. 첫 번째 예에서는 a DirectoryIterator이고 두 번째 예에서는 IteratorIterator. 이는 반복기가 갖는 유연성을 보여줍니다. 서로 교체 할 수 있으며 내부 코드 foreach는 예상대로 계속 작동합니다.

하위 디렉터리를 포함하여 전체 목록을 가져 오겠습니다.

이제 반복 유형을 지정 했으므로 다른 유형의 반복으로 변경해 보겠습니다.

우리는 이제 첫 번째 레벨뿐만 아니라 전체 트리를 횡단해야한다는 것을 알고 있습니다. 단순하게 작동하려면 foreach다른 유형의 반복자가 필요합니다 RecursiveIteratorIterator.. 그리고 그 RecursiveIterator인터페이스 가있는 컨테이너 객체에 대해서만 반복 할 수 있습니다 .

인터페이스는 계약입니다. 이를 구현하는 모든 클래스는 RecursiveIteratorIterator. 이러한 클래스의 예는 RecursiveDirectoryIterator의 재귀 변형과 같은입니다 DirectoryIterator.

I-word로 다른 문장을 작성하기 전에 첫 번째 코드 예제를 살펴 보겠습니다.

$dir  = new RecursiveDirectoryIterator($path);

echo "[$path]\n";
foreach ($dir as $file) {
    echo " ├ $file\n";
}

이 세 번째 예제는 첫 번째 예제와 거의 동일하지만 몇 가지 다른 출력을 생성합니다.

[tree]
 ├ tree\.
 ├ tree\..
 ├ tree\dirA
 ├ tree\fileA

좋아, 그렇게 다르지는 않지만 이제 파일 이름 앞에 경로 이름이 포함되어 있지만 나머지도 비슷해 보입니다.

예제에서 알 수 있듯이 디렉토리 객체는 이미 RecursiveIterator인터페이스를 구현하지만 아직 foreach전체 디렉토리 트리를 순회 하기에는 충분하지 않습니다 . 이것이 RecursiveIteratorIterator행동으로 오는 곳 입니다. 예 4 는 방법을 보여줍니다.

$files = new RecursiveIteratorIterator($dir);

echo "[$path]\n";
foreach ($files as $file) {
    echo " ├ $file\n";
}

은 Using RecursiveIteratorIterator대신 이전의 $dir오브젝트하는 것 foreach재귀 방식으로 모든 파일과 디렉토리를 통해 통과 할 수 있습니다. 그러면 이제 객체 반복 유형이 지정되었으므로 모든 파일이 나열됩니다.

[tree]
 ├ tree\.
 ├ tree\..
 ├ tree\dirA\.
 ├ tree\dirA\..
 ├ tree\dirA\dirB\.
 ├ tree\dirA\dirB\..
 ├ tree\dirA\dirB\fileD
 ├ tree\dirA\fileB
 ├ tree\dirA\fileC
 ├ tree\fileA

이것은 플랫과 트리 순회의 차이를 이미 보여 주어야합니다. 은 RecursiveIteratorIterator요소의 목록으로 어떤 트리 구조를 탐색 할 수 있습니다. 더 많은 정보 (예 : 현재 반복이 발생하는 수준)가 있기 때문에 반복하는 동안 반복기 객체에 액세스 할 수 있습니다 (예 : 출력 들여 쓰기).

echo "[$path]\n";
foreach ($files as $file) {
    $indent = str_repeat('   ', $files->getDepth());
    echo $indent, " ├ $file\n";
}

그리고 예제 5의 출력 :

[tree]
 ├ tree\.
 ├ tree\..
    ├ tree\dirA\.
    ├ tree\dirA\..
       ├ tree\dirA\dirB\.
       ├ tree\dirA\dirB\..
       ├ tree\dirA\dirB\fileD
    ├ tree\dirA\fileB
    ├ tree\dirA\fileC
 ├ tree\fileA

물론 미인 대회에서이기는 것은 아니지만 재귀 반복기를 사용하면 의 선형 순서보다 더 많은 정보를 사용할 수 있음을 보여줍니다 . foreach이러한 종류의 선형성을 표현할 수만 있어도 반복자 자체에 액세스하면 더 많은 정보를 얻을 수 있습니다.

메타 정보와 유사하게 트리를 순회하여 출력 순서를 지정하는 방법도 여러 가지가 있습니다. 이것은의 모드 이며RecursiveIteratorIterator 생성자로 설정할 수 있습니다.

다음 예제 에서는 필요하지 않은 RecursiveDirectoryIterator점 항목 ( ...) 을 제거 하도록에 지시 합니다. 그러나 재귀 모드는 하위 (하위 디렉터리 SELF_FIRST의 파일 및 하위 디렉터리)보다 먼저 상위 요소 (하위 디렉터리)를 먼저 ( ) 가져 오도록 변경됩니다.

$dir  = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);

echo "[$path]\n";
foreach ($files as $file) {
    $indent = str_repeat('   ', $files->getDepth());
    echo $indent, " ├ $file\n";
}

이전 출력과 비교하면 출력에 제대로 나열된 하위 디렉토리 항목이 표시됩니다.

[tree]
 ├ tree\dirA
    ├ tree\dirA\dirB
       ├ tree\dirA\dirB\fileD
    ├ tree\dirA\fileB
    ├ tree\dirA\fileC
 ├ tree\fileA

따라서 재귀 모드는 디렉토리 예제의 경우 트리에서 brach 또는 leaf가 반환되는 대상과시기를 제어합니다.

  • LEAVES_ONLY (기본값) : 디렉토리없이 파일 만 나열합니다.
  • SELF_FIRST (위) : 디렉토리와 그 안에있는 파일을 나열합니다.
  • CHILD_FIRST (예제없이) : 먼저 하위 디렉토리의 파일을 나열한 다음 디렉토리를 나열합니다.

다른 두 가지 모드가있는 예제 5의 출력 :

  LEAVES_ONLY                           CHILD_FIRST

  [tree]                                [tree]
         ├ tree\dirA\dirB\fileD                ├ tree\dirA\dirB\fileD
      ├ tree\dirA\fileB                     ├ tree\dirA\dirB
      ├ tree\dirA\fileC                     ├ tree\dirA\fileB
   ├ tree\fileA                             ├ tree\dirA\fileC
                                        ├ tree\dirA
                                        ├ tree\fileA

표준 순회와 비교할 때이 모든 것을 사용할 수 없습니다. 따라서 재귀 반복은 머리를 감싸 야 할 때 조금 더 복잡하지만 반복자처럼 작동하기 때문에 사용하기 쉽습니다 foreach.

나는 이것들이 하나의 대답에 대한 충분한 예라고 생각합니다. 이 요점에서 멋진 아스키 트리를 표시하는 예제와 전체 소스 코드를 찾을 수 있습니다 : https://gist.github.com/3599532

스스로를 수행 만들기 기능 RecursiveTreeIterator선으로 직장 선.

예제 5 는 사용 가능한 반복기의 상태에 대한 메타 정보가 있음을 보여줍니다. 그러나 이것은 반복 에서 의도적으로 입증되었습니다 foreach. 실제 생활에서 이것은 자연스럽게 RecursiveIterator.

더 좋은 예는 RecursiveTreeIterator이며 들여 쓰기, 접두사 등을 처리합니다. 다음 코드 조각을 참조하십시오.

$dir   = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
$lines = new RecursiveTreeIterator($dir);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));

RecursiveTreeIterator라인으로 작업 라인에 의도, 출력은 꽤 똑바로 앞으로 하나 개의 작은 문제에있다 :

[tree]
 ├ tree\dirA
 │ ├ tree\dirA\dirB
 │ │ └ tree\dirA\dirB\fileD
 │ ├ tree\dirA\fileB
 │ └ tree\dirA\fileC
 └ tree\fileA

와 함께 사용 RecursiveDirectoryIterator하면 파일 이름뿐만 아니라 전체 경로 이름이 표시됩니다. 나머지는 좋아 보인다. 파일 이름은 SplFileInfo. 대신 기본 이름으로 표시되어야합니다. 원하는 출력은 다음과 같습니다.

/// Solved ///

[tree]
 ├ dirA
 │ ├ dirB
 │ │ └ fileD
 │ ├ fileB
 │ └ fileC
 └ fileA

RecursiveTreeIterator대신에 사용할 수있는 데코레이터 클래스를 만듭니다 RecursiveDirectoryIterator. SplFileInfo경로 이름 대신 현재의 기본 이름을 제공해야합니다 . 최종 코드 조각은 다음과 같습니다.

$lines = new RecursiveTreeIterator(
    new DiyRecursiveDecorator($dir)
);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));

다음을 포함 $unicodeTreePrefix하는 이러한 단편 은 부록 : Do It Yourself : Make the RecursiveTreeIteratorWork Line by Line 의 요점의 일부입니다 . .


제시된 질문에 답하지 않고 사실에 근거한 오류를 포함하며 반복 사용자 정의로 이동할 때 핵심 포인트를 놓칩니다. 대체로, 당신이 많이 알지 못하는 주제에 대해 현상금을 얻으려는 시도는 좋지 않은 것처럼 보이며, 만약 당신이 그렇게한다면 제시된 질문에 대한 답으로 추출 할 수 없습니다.
salathe

2
내 "왜"질문에 대답하지 않는 글쎄요, 당신은 말을 많이하지 않고 더 많은 단어를 만들뿐입니다. 실제로 중요한 오류로 시작할 수 있습니까? 그것을 지적하고 비밀로 유지하지 마십시오.
hakre

첫 번째 문장이 잘못되었습니다. "RecursiveIteratorIterator는…을 지원하는 IteratorIterator입니다.", 이것은 사실이 아닙니다.
salathe

1
@salathe : 귀하의 피드백을 위해 당신을 탱크. 나는 그것을 해결하기 위해 대답을 편집했습니다. 첫 번째 문장은 실제로 잘못되었고 불완전했습니다. RecursiveIteratorIterator이것은 다른 유형과 공통점이 있기 때문에 구체적인 구현 세부 사항을 여전히 생략 했지만 실제로 작동하는 방법에 대한 기술 정보를 제공했습니다. 내가 생각하는 예는 잘 차이를 보여 반복의 유형 입니다 둘 간의 주요한 차이가있다. 반복 유형을 구입하면 조금 다르게 동전을 만들지 모르지만 IMHO는 반복의 의미 유형이 쉽지 않습니다.
hakre

1
첫 번째 부분은 다소 개선되었지만 일단 예제로 넘어 가면 여전히 사실적인 부정확성을 보입니다. 수평 규칙에서 답을 자르면 훨씬 개선 될 것입니다.
salathe

32

IteratorIterator과 의 차이점은 무엇입니까 RecursiveIteratorIterator?

이 두 반복자의 차이점을 이해하려면 먼저 사용 된 명명 규칙과 "재귀"반복자가 의미하는 바에 대해 약간 이해해야합니다.

재귀 및 비 재귀 반복기

PHP 같은 비 "순환"이터레이터 가지고 ArrayIteratorFilesystemIterator. 등으로 "재귀"반복자도있다 RecursiveArrayIterator하고 RecursiveDirectoryIterator. 후자는 드릴 다운 할 수있는 방법이 있지만 전자는 그렇지 않습니다.

이러한 반복기의 인스턴스가 자체적으로 반복되는 경우, 심지어 반복되는 경우에도 하위 디렉토리가있는 중첩 배열 또는 디렉토리를 반복하더라도 값은 "최상위"수준에서만 제공됩니다.

재귀 반복자는 구현 (를 통해 반복적 동작을 hasChildren(), getChildren())하지 않지만 공격 을.

"recursible"반복자는, 그들이 가지고있는 재귀 반복자 생각하는 더 좋을 수도 기능을 반복적으로 단순히 그렇게하지 않습니다 이러한 클래스 중 하나의 인스턴스를 반복하는 반복 될 수 있습니다. 재귀 적 행동을 이용하려면 계속 읽으십시오.

RecursiveIteratorIterator

이것은 RecursiveIteratorIterator플레이에 오는 곳 입니다. 일반, 플랫, 루프에서 구조로 드릴 다운하는 방식으로 "재귀 가능"반복자를 호출하는 방법에 대한 지식을 가지고 있습니다. 재귀 적 동작을 실행합니다. 그것은 본질적으로 반복기의 각 값을 단계별로 실행하고, 반복 할 "자식"이 있는지 확인하고, 이러한 자식 컬렉션에 들어오고 나가는 작업을 수행합니다. 당신의 인스턴스를 스틱 RecursiveIteratorIteratorforeach 문에, 그리고 그것은 당신이하지 않도록 구조로 다이빙.

RecursiveIteratorIterator사용하지 않았다면 재귀 동작을 이용하기 위해 자신의 재귀 루프를 작성하고 "재귀"반복자를 확인 hasChildren()하고 getChildren().

에 대한 간략한 개요입니다.과 ( RecursiveIteratorIterator와) 어떻게 다른 IteratorIterator가요? 글쎄, 당신은 기본적으로 고양이와 나무의 차이점이 무엇입니까? 와 같은 종류의 질문을 하고 있습니다. 둘 다 동일한 백과 사전 (또는 반복기의 경우 매뉴얼)에 표시된다고해서 둘을 혼동해야하는 것은 아닙니다.

반복자

의 임무는 IteratorIterator모든 Traversable객체 를 가져와 Iterator인터페이스를 만족하도록 감싸는 것 입니다. 이를위한 용도는 비 반복기 객체에 반복기 특정 동작을 적용 할 수 있다는 것입니다.

실제 예제를 제공하기 위해, DatePeriod클래스는 Traversable하지만 아닙니다 Iterator. 따라서 값을 반복 할 수는 foreach()있지만 일반적으로 반복기에서 수행하는 다른 작업 (예 : 필터링)은 수행 할 수 없습니다.

작업 : 다음 4주의 월요일, 수요일, 금요일을 반복합니다.

예, 이것은 루프 내에서 foreach-ing DatePeriod및 사용하여 사소한 것입니다 if(). 그러나 그것은이 예제의 요점이 아닙니다!

$period = new DatePeriod(new DateTime, new DateInterval('P1D'), 28);
$dates  = new CallbackFilterIterator($period, function ($date) {
    return in_array($date->format('l'), array('Monday', 'Wednesday', 'Friday'));
});
foreach ($dates as $date) { … }

위의 스 니펫은 인터페이스 CallbackFilterIterator를 구현하는 클래스의 인스턴스를 예상 하기 때문에 작동 하지 않습니다. 그러나 를 사용하면 그 요구 사항을 쉽게 충족시킬 수 있습니다 .IteratorDatePeriodTraversableIteratorIterator

$period = new IteratorIterator(new DatePeriod(…));

보시다시피, 이것은 반복자 클래스 또는 재귀에 대한 반복과 관련 이 없으며 그 안에 IteratorIterator와 사이의 차이가 RecursiveIteratorIterator있습니다.

요약

RecursiveIteraratorIteratorRecursiveIterator( "재귀"반복자) 를 반복 하여 사용 가능한 재귀 동작을 이용합니다.

IteratorIteratorIterator반복자가 아닌 Traversable객체에 동작을 적용하기위한 것 입니다.


아닌가 IteratorIterator에 대한 선형 주문 탐색의 표준 유형의 단지 Traversable객체는? 그것없이 그대로 사용할 수있는 foreach것? 그리고 더욱, a는 아니다 RecursiveIterator 항상Traversable 때문에뿐만 IteratorIterator아니라 RecursiveIteratorIterator항상 "적용을위한 Iterator비 반복자는,에 이동 객체에 동작을" ? (이제 foreach반복자 유형 인터페이스를 구현하는 컨테이너 객체에 반복자 객체를 통해 반복 유형을 적용 한다고 말하고 싶습니다. 그래서 이들은 항상 반복자-컨테이너 객체입니다. Traversable)
hakre

내 대답 상태로, IteratorIterator포장에 대한 모든 인 클래스입니다 Traversable의 객체 Iterator. 더 이상은 없습니다 . 더 일반적으로 용어를 적용하는 것 같습니다.
salathe

겉보기에 유익한 답변. 한 가지 질문은 RecursiveIteratorIterator도 개체를 래핑하여 Iterator 동작에 액세스 할 수 있도록하는 것입니다. 둘 사이의 유일한 차이점은 RecursiveIteratorIterator는 드릴 다운 할 수있는 반면 IteratorIterator는 드릴 다운 할 수 없다는 것입니다.
Mike Purcell

@salathe, 재귀 반복기 (RecursiveDirectoryIterator)가 hasChildren (), getChildren () 동작을 구현하지 않는 이유를 알고 있습니까?
anru

8
"재귀 가능"이라고 말하면 +1. Recursivein은 RecursiveIterator행동 을 암시 하기 때문에 그 이름은 오랫동안 나를 타락하게 만들었습니다 RecursibleIterator. 반면에 더 적합한 이름은 .
goat

0

와 함께 사용하면 iterator_to_array(), RecursiveIteratorIterator재귀 적으로 모든 값을 찾을 수있는 배열을 안내합니다. 원래 배열을 평평하게한다는 의미입니다.

IteratorIterator 원래 계층 구조를 유지합니다.

이 예는 차이점을 명확하게 보여줍니다.

$array = array(
               'ford',
               'model' => 'F150',
               'color' => 'blue', 
               'options' => array('radio' => 'satellite')
               );

$recursiveIterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
var_dump(iterator_to_array($recursiveIterator, true));

$iterator = new IteratorIterator(new ArrayIterator($array));
var_dump(iterator_to_array($iterator,true));

이것은 완전히 오해의 소지가 있습니다. new IteratorIterator(new ArrayIterator($array))에 해당 new ArrayIterator($array), 즉, 외부 IteratorIterator아무것도하지 않고있다. 더욱이 출력의 평면화는 아무 관련이 없습니다. iterator_to_array단지 반복기를 배열로 변환하는 것입니다. 평탄화는 RecursiveArrayIterator내부 반복자를 걷는 방식의 속성입니다 .
Quolonel 질문

0

RecursiveDirectoryIterator는 파일 이름뿐만 아니라 전체 경로 이름을 표시합니다. 나머지는 좋아 보인다. 파일 이름이 SplFileInfo에 의해 생성되기 때문입니다. 대신 기본 이름으로 표시되어야합니다. 원하는 출력은 다음과 같습니다.

$path =__DIR__;
$dir = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($dir,RecursiveIteratorIterator::SELF_FIRST);
while ($files->valid()) {
    $file = $files->current();
    $filename = $file->getFilename();
    $deep = $files->getDepth();
    $indent = str_repeat('│ ', $deep);
    $files->next();
    $valid = $files->valid();
    if ($valid and ($files->getDepth() - 1 == $deep or $files->getDepth() == $deep)) {
        echo $indent, "├ $filename\n";
    } else {
        echo $indent, "└ $filename\n";
    }
}

산출:

tree
 ├ dirA
 │ ├ dirB
 │ │ └ fileD
 │ ├ fileB
 │ └ fileC
 └ fileA
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.