#!perl -w use strict; use Data::Dumper 'Dumper'; my %ranges = ( a => [11,22], b => [22,45], # etc ); my %r2 = %ranges; # need copy to reentrantly iterate over %ranges # perl sucks sometimes. my %results; while (my ($name,$range) = each %ranges) { while (my ($name2,$range2) = each %r2) { if ($name ne $name2 and $range->[0] <= $range2->[0] && $range->[1] >= $range2->[0]) { push @{$results{$name}},$name2; } } $results{$name} ||= []; } print Dumper(\%results);