123-234-339-456-567 117-234-339 131 213-339-456 372 #### #!/usr/bin/perl -w use strict; my @data = ( [ 567, 456 ], [ 456, 345 ], [ 345, 234 ], [ 234, 123 ], [ 339, 228 ], [ 228, 117 ], [ 131, undef ], [ 435, 324 ], [ 324, 213 ], [ 372, undef ] ); sub replace { my ( $num_first_ref, $pred_num_ref, $num, $pred ) = @_; # Catch the first number in the chain $num_first_ref->{ $pred } = $pred; # Assign current $pred as possible first $num_first_ref->{ $num } = $pred; # Use reverse hash to look up later/higher numbers and update if ( exists( $pred_num_ref->{ $num } ) && ( my $higher_num = $pred_num_ref->{ $num } ) ) { # Reassign current $pred as possible first $num_first_ref->{ $higher_num } = $pred; replace( $num_first_ref, $pred_num_ref, $higher_num, $pred ); } } my %num_first; # Calculated data for output goes here my %pred_num; # 'Reverse' hash for recursive lookup for my $nums ( @data ) { # Handle single values unless ( defined( $nums->[ 1 ] ) ) { $num_first{ $nums->[ 0 ] } = $nums->[ 0 ]; next; } # Load reverse hash with predecessor as key $pred_num{ $nums->[ 1 ] } = $nums->[ 0 ]; replace( \%num_first, \%pred_num, $nums->[ 0 ], $nums->[ 1 ] ); } for my $high_num ( sort { $a <=> $b } keys %num_first ) { print "$high_num => $num_first{ $high_num }\n"; } Output: 117 => 117 123 => 123 131 => 131 213 => 213 228 => 117 234 => 123 324 => 213 339 => 117 345 => 123 372 => 372 435 => 213 456 => 123 567 => 123