• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • iterator_apply()

    (PHP 5 >= 5.1.0, PHP 7)

    为迭代器中每个元素调用一个用户自定义函数

    说明

    iterator_apply(Traversable$iterator,callable $function[,array $args]): int

    循环迭代每个元素时调用某一回调函数。

    参数

    $iterator

    需要循环迭代的类对象。

    $function

    迭代到每个元素时的调用的回调函数。

    Note:为了遍历$iterator这个函数必须返回TRUE

    $args

    传递到回调函数的参数。

    返回值

    返回已迭代的元素个数。

    范例

    iterator_apply() example

    <?php
    function print_caps(Iterator $iterator) {
        echo strtoupper($iterator->current()) . "\n";
        return TRUE;
    }
    $it = new ArrayIterator(array("Apples", "Bananas", "Cherries"));
    iterator_apply($it, "print_caps", array($it));
    ?>
    

    以上例程会输出:

    APPLES
    BANANAS
    CHERRIES
    

    参见

    • array_walk()使用用户自定义函数对数组中的每个元素做回调处理
    Each of the arguments required by the function, must be in the array supplied in the third argument to iterator_apply. You can use references too. Example:
    <?php
    function translate_to(string $target_language, Iterator $words, array $dictionaries) {
      
      $language = ucfirst($target_language);
      $dictionary = $dictionaries[$target_language] ?? 'not found';
      
      if ($dictionary === 'not found') {
        echo "Not found dictionary for {$language}\n";
        return;
      }
      
      echo "English words translated to {$language}\n";
      
      $not_found = [];
      
      iterator_apply($words, function($words, $dictionary, &$not_found){
      
        $english_word = $words->current();
      
        $translated_word = $dictionary[$english_word] ?? '';
      
        if ($translated_word !== '') {
          echo "{$english_word} translates to {$translated_word}\n";
        } else {
          $not_found[] = $english_word;
        }
        return true;
      
      }, array($words, $dictionary, &$not_found));
      
      echo "\nNot found words:\n" . implode("\n", $not_found) . "\n";
    }
    $dictionaries = [
      'nahuatl' => [
        'one' => 'Ze',
        'two' => 'Ome',
        'three' => 'Yei',
        'four' => 'Nahui',
      ],
    ];
    $iterator = new \ArrayIterator(array('one', 'two', 'three', 'four', 'gasoil'));
    translate_to('nahuatl', $iterator, $dictionaries);
    ?>
    English words translated to Nahuatl
    one translates to Ze
    two translates to Ome
    three translates to Yei
    four translates to Nahui
    Not found words:
    gasoil
    Be aware of the proper methods to iterate the specific Iterator you are consuming, as the implementation of the method could vary its behaviour.
    For example, unlike the ArrayIterator, you can't iterate on a SplDoubleLinkedList with current() without using next() on every iteration (and then, only would iterate if you return true at the end of the callable. It is far easier then with LinkedLists use a while($it->valid()) { $it->current(); $it->next(); }
    Let's see:
    <?php
    $ll = new \SplDoublyLinkedList();
    $ll->push('ze');
    $ll->push('ome');
    $ll->push('yei');
    $ll->push('nahui');
    $ll->rewind();
    $iterations_done = iterator_apply($ll, function(Iterator $it) {
      echo implode("\t=>", [
        $it->key(),
        $it->current(),
        ucfirst($it->current())
      ]),"\n";
      
      return true;
    }, array($ll));
    echo "Did iterate {$iterations_done} times \n";
    $ll->rewind();
    $iterations_done = iterator_apply($ll, function(Iterator $it) {
      echo implode("\t=>", [
        $it->key(),
        $it->current(),
        ucfirst($it->current())
      ]),"\n";
      
      $it->next();
      
      return true;
    }, array($ll));
    echo "Did iterate {$iterations_done} times \n";
    $ll->setIteratorMode(SplDoublyLinkedList::IT_MODE_FIFO | SplDoublyLinkedList::IT_MODE_DELETE);
    var_dump($ll->count());
    foreach($ll as $key => $val) {
      echo "{$key}\t",ucfirst($val),"\n";
    }
    var_dump($ll->count());
    ?>
    Output:
    0  =>ze  =>Ze
    0  =>ze  =>Ze
    0  =>ze  =>Ze
    0  =>ze  =>Ze
    Did iterate 4 times 
    0  =>ze  =>Ze
    1  =>ome  =>Ome
    2  =>yei  =>Yei
    3  =>nahui  =>Nahui
    Did iterate 4 times 
    int(4)
    0  Ze
    0  Ome
    0  Yei
    0  Nahui
    int(0)
    $args is an array and each of its elements are passed to the callback as separate arguments.
    so this is the right way to get args:
    <?php
    $ai = new ArrayIterator(range(0, 2));
    iterator_apply($ai, function() {
      var_dump(func_get_args());   // use this func
      return true;
    }, array(1, 2));
    ?>
    output: 
    array(2) {
     [0] =>
     int(1)
     [1] =>
     int(2)
    }
    array(2) {
     [0] =>
     int(1)
     [1] =>
     int(2)
    }
    array(2) {
     [0] =>
     int(1)
     [1] =>
     int(2)
    }
    --------------------------------------------------
    or list each args:
    <?php
    $ai = new ArrayIterator(range(0, 2));
    iterator_apply($ai, function($arg1, $arg2, $arg3) {
      var_dump([$arg1, $arg2, $arg3]);
      return true;
    }, array(1, 2));
    ?>
    same output.

    上篇:class_uses()

    下篇:iterator_count()