in reply to deleteing array elements I get mad!!

Taking Jenda's response just a step further, rather than use splice (which still could damage the foreach's ability to loop properly, as per Fletch's comment), use grep.

sub man_cfs { my ($cashflow, $valid_ports) = @_; @$cashflow = grep { # only keep the ones whose portfolio_id is not empty. $_->{'portfolio_id'} ne '' } @$cashflow; # loop through the new @$cashflow to do other stuff.
There are other ways to check for the portfolio_id's truthiness. If 0 is not a valid value, you could just remove the ne '' bit, and let perl evaluate the string in boolean context. If 0 is a valid value, perhaps the portfolio_id element may not exist. In the interests of being fully strict-compliant, perhaps you want exists $_->{'portfolio_id'} and length $_->{'portfolio_id'} - that it both exists, and has a non-zero length, then keep it.

Hope that helps,