hack集合:Iterating

2018-10-25 11:49 更新

集合通过迭代(Iterating)foreach

<?hh

namespace Hack\UserDocumentation\Collections\Iterating\Examples\FEach;

function run(): void {
  $vec = Vector {'A', 'B', 'C'};
  $map = Map {'A' => 1, 'B' => 2};
  $set = Set {800, 900, 1000};
  $pair = Pair {'A', 'B'};

  foreach ($vec as $val) {
    var_dump($val);
  }

  foreach ($map as $key => $val) {
    var_dump($key);
    var_dump($val);
  }

  foreach ($set as $val) {
    var_dump($val);
  }

  foreach ($pair as $key => $val) {
    var_dump($key);
    var_dump($val);
  }
}

run();

Output

string(1) "A"
string(1) "B"
string(1) "C"
string(1) "A"
int(1)
string(1) "B"
int(2)
int(800)
int(900)
int(1000)
int(0)
string(1) "A"
int(1)
string(1) "B"

注意事项

当使用它foreach来迭代集合时,有几点值得注意的注意事项。

修改集合

不允许从集合添加或删除项目,如果尝试,将导致一个InvalidOperationException。

<?hh

namespace Hack\UserDocumentation\Collections\Iterating\Examples\Modifying;

function run(): void {
  $vec = Vector {'A', 'B', 'C'};

  try {
    foreach ($vec as $val) {
      if ($val === 'B') {
        // This will actually be allowed, but the next time through the loop
        // the InvalidOperationException will be thrown.
        $vec[] = 'D';
      }
      var_dump($vec);
      var_dump($val);
    }
  } catch (\InvalidOperationException $ex) {
    var_dump($ex->getMessage());
  }

  $set = Set {100, 200, 300};

  try {
    foreach ($set as $val) {
      if ($val === 300) {
        // This will actually be allowed, and even though this is the last
        // element in the set, we actually do the check in the foreach again so
        // the InvalidOperationException will be thrown.
        $set->remove(300);
      }
      var_dump($set);
      var_dump($val);
    }
  } catch (\InvalidOperationException $ex) {
    var_dump($ex->getMessage());
  }
}

run();

Output

object(HH\Vector)#1 (3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  string(1) "C"
}
string(1) "A"
object(HH\Vector)#1 (4) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  string(1) "C"
  [3]=>
  string(1) "D"
}
string(1) "B"
string(40) "Collection was modified during iteration"
object(HH\Set)#3 (3) {
  int(100)
  int(200)
  int(300)
}
int(100)
object(HH\Set)#3 (3) {
  int(100)
  int(200)
  int(300)
}
int(200)
object(HH\Set)#3 (2) {
  int(100)
  int(200)
}
int(300)
string(40) "Collection was modified during iteration"

请注意,在该示例中,实际的添加或删除将生效,但是当我们回到循环迭代检查时将抛出异常。

参考

您不能通过foreach引用作为集合。

foreach ($vec as &$val)

这将导致致命的错误,甚至不是例外。

有一种模拟这种行为的方法。

<?hh

namespace Hack\UserDocumentation\Collections\Iterating\Examples\Reference;

function run(): void {
  $arr = array ('A', 'B', 'C');
  // if $arr was a Vector instead, we would get a
  // Fatal error: Collection elements cannot be taken by reference
  var_dump($arr);
  foreach ($arr as &$val) {
    var_dump($val);
    if ($val === 'B') {
      $val = 'D';
    }
    var_dump($arr);
  }

  // How to mimic the above
  $vec = Vector {'A', 'B', 'C'};
  var_dump($vec);
  foreach ($vec as $key => $val) {
    var_dump($val);
    if ($val === 'B') {
      $vec[$key] = 'D';
    }
    var_dump($vec);
  }
}

run();

Output

array(3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  string(1) "C"
}
string(1) "A"
array(3) {
  [0]=>
  &string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  string(1) "C"
}
string(1) "B"
array(3) {
  [0]=>
  string(1) "A"
  [1]=>
  &string(1) "D"
  [2]=>
  string(1) "C"
}
string(1) "C"
array(3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "D"
  [2]=>
  &string(1) "C"
}
object(HH\Vector)#1 (3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  string(1) "C"
}
string(1) "A"
object(HH\Vector)#1 (3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  string(1) "C"
}
string(1) "B"
object(HH\Vector)#1 (3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "D"
  [2]=>
  string(1) "C"
}
string(1) "C"
object(HH\Vector)#1 (3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "D"
  [2]=>
  string(1) "C"
}

基本上,您明确拉出集合的键/值对,然后显式修改键的值。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号