hack集合:Iterating
集合通过迭代(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"
}
基本上,您明确拉出集合的键/值对,然后显式修改键的值。