my %info; while (<>) { my ($time, $id, $state) = parse_me ($_); unless ($info {$id}) { next unless $state eq 'open'; $info {$id} = [$state, $time, 0]; next; } if ($state eq 'open') { next unless $info {$id} -> [0] eq 'open'; $info {$id} -> [0] = 'open'; $info {$id} -> [1] = $time; next; } next unless $info {$id} -> [0] eq 'open'; # This means the previous state was "open", and the current # state is "hold" or "closed". Increment the time. $info {$id} -> [2] += $time - $info {$id} -> [1]; $info {$id} -> [0] = $state; $info {$id} -> [1] = $time; # Not really needed. } # Finally, for all "open" cases, add the time since it went # "open" till now. my $time = time; while (my ($id, $info) = each %info) { next unless $info -> [0] eq 'open'; $info -> [2] += $time - $info -> [1]; }