Yes, the foreach loop is working on a copy, but when you are calling unset() you are still, in fact, unsetting that element, even though you haven't changed the copy that the foreach loop is iterating through... so even though the actual array has been changed, the foreach loop doesn't know that, so to speak... you could simply add this check to your code, skipping the iteration if that element has been unset:
foreach ($test as $keyA=>$valueA){
if (!isset($test[$keyA])) continue;
echo "I am at item ".$valueA." [".$keyA."]<br>";
// etc...
}
The output becomes this, which if I understand your question is what you're looking for:
I am at item a [0]
=> comparing to b [1]
=> comparing to c [2]
=> comparing to b [3]
=> comparing to c [4]
I am at item b [1]
=> comparing to a [0]
=> comparing to c [2]
=> comparing to b [3]-- joined and removed [3]
=> comparing to c [4]
I am at item c [2]
=> comparing to a [0]
=> comparing to bb [1]
=> comparing to c [4]-- joined and removed [4]