Each $string .= ... returns the new contents of $string.
map builds an array with the values of last statment execuded in it's block. This cost both time and memory.
in reply to Don't cargo cult "advice"
in thread Returning regexp pattern that was used to match
foreach does not keep the values it's block returns so it will run faster than map.
The OP's code did not use any of the results a concatination assignment (other than the actual concationation assignment side effect) so keeping the results around is a waste.
In the case of assignment or print your usualy not interested in the direct result, only the side effect. So storing the result is a waste of time and memory.
See What's wrong with using grep or map in a void context?
This was changed in 5.8.1 (map only, grep should still be avoided in void context), but as there are plenty of installs running perls prior to that it's still a bad idea.