in reply to Converting a growing hash into an array of arrays

If you've got a lot of data to work with, you really want to do your incrementing updates with a hash, otherwise you will be scanning through every element of the $data[0] array every time you want to increment. The number of compares goes up with the square of the number of log entries, which can get expensive. (The solutions by jmcada and holli, however, are nice and clear, and are efficient if the number of elements in the sub-arrays don't get too long. I'd go with that approach if your logs are short.)

The sub below uses an external hash of references to the elements of $data[1], called %data_refs_hash. Using that hash you can do the increment directly. You only need to scan through the array when you're adding a new key (and you only need to do that if you're keeping the keys in order, if not, leave out the while() scan and just push the new values on the end instead of splicing them.)

sub IncrData { my $key = shift; if (exists $data_refs_hash{$key} ) { # if there's a hash entry ${$data_refs_hash{$key}}++; # increment it } else { # otherwise, find a spot and put one in my $idx = 0; my $endIdx = scalar(@{$data[0]}); while ($idx < $endIdx && $data[0][$idx] < $key) { $idx++; } splice(@{$data[0]},$idx,0,$key); splice(@{$data[1]},$idx,0,1); $data_refs_hash{$key} = \$data[1][$idx]; } # if you need to update the sort each time, then do @{$data[2]} = sort { $a <=> $b } @{$data[1]}; # but you shouldn't update it until you're going to use it, # since it's expensive to sort for every increment } # IncrData
And here's the demo and testing portion
my @data = ( ["1.6","2.2","3.4","3.6","5.4","6.2","7.1", "8.1", "9.0"], [ 1, 2, 5, 6, 3, 15, 4, 3, 4], [ sort { $a <=> $b } (1, 2, 5, 6, 3, 15, 4, 3, 4) ] ); # create a hash of refs to the things you want to updated. # This is only needed for the example, so that we can # use the ininialized array above. Normally, the hash is just updated # each time a new element is added to the arrays in IcrData(). for $idx (0..$#{$data[0]} ) { $data_refs_hash{$data[0][$idx]} = \$data[1][$idx]; } print join(", ", @{$data[1]}), "\n"; IncrData("3.4"); IncrData("3.5"); IncrData("9.5"); IncrData("1.1"); IncrData("9.5"); print "\n"; print join(", ", @{$data[0]}), "\n"; print join(", ", @{$data[1]}), "\n"; print join(", ", @{$data[2]}), "\n"; #produces 1.1, 1.6, 2.2, 3.4, 3.5, 3.6, 5.4, 6.2, 7.1, 8.1, 9.0, 9.5 1, 1, 2, 6, 1, 6, 3, 15, 4, 3, 4, 2 1, 1, 1, 2, 2, 3, 3, 4, 4, 6, 6, 15
Updated: Reformatted code to move testing into "readmore" and revised non-code portion