my @ends = map{ [$_->[0], $_, 'S'], [$_->[-1], $_, 'E'] } @data; #### @ends = sort{ $b->[0]{X} <=> $a->[0]{X} || $b->[0]{Y} <=> $a->[0]{Y} || $b->[2] cmp $a->[2] } @ends; #### sub mapAdjPairs (&@) { my $code = shift; map { local ($a, $b) = (shift, $_[0]); $code->() } 0 .. @_-2; } #### my @merged = mapAdjPairs{ if ($a->[2] eq 'S') { # $a is a start point if ( $b->[2] eq 'E' and $a->[0]{X} == $b->[0]{X} # Introduce FP fudge factor if needed and $a->[0]{Y} == $b->[0]{Y} ) { # $b is and end and we found a coincident end/start pair push @{ $b->[1] }, @{ $a->[1] }[1.. $#{$a->[1]} ]; return; # we merged two sections so don't add to result } else { # We have a start point and didn't merge so add to the results return $a->[1]; } } return; } @ends, $ends[0]; # Note:Repeat first element last to complete cycle #### c:\test>240810 X 11 Y 12 X 12 Y 13 X 13 Y 14 X 14 Y 15 X 15 Y 16 X 16 Y 17 X 17 Y 18 X 18 Y 19 X 19 Y 20 X 10 Y 10 X 11 Y 11 X 12 Y 12 X 13 Y 13 X 14 Y 14 X 15 Y 15 X 16 Y 16 X 17 Y 17 X 18 Y 18 X 19 Y 19 X 20 Y 20 X 21 Y 21 X 22 Y 22 X 23 Y 23 X 24 Y 24 X 1 Y 2 X 1 Y 3 X 1 Y 4 c:\test> #### #! perl -slw use strict; # Steps through an array two at a time [0,1], the [1,2] etc sub mapAdjPairs (&@) { my $code = shift; map { local ($a, $b) = (shift, $_[0]); $code->() } 0 .. @_-2; } my @data = ( [ {X=>10, Y=>10}, {X=>11, Y=>11}, {X=>12, Y=>12}, ], [ {X=>11, Y=>12}, {X=>12, Y=>13}, {X=>13, Y=>14}, {X=>14, Y=>15}, ], [ {X=>20, Y=>20}, {X=>21, Y=>21}, {X=>22, Y=>22}, {X=>23, Y=>23}, {X=>24, Y=>24}, ], [ {X=>17, Y=>17}, {X=>18, Y=>18}, {X=>19, Y=>19}, {X=>20, Y=>20}, ], [ {X=>01, Y=>02}, {X=>01, Y=>03}, {X=>01, Y=>04}, ], [ {X=>12, Y=>12}, {X=>13, Y=>13}, {X=>14, Y=>14}, {X=>15, Y=>15}, {X=>16, Y=>16}, {X=>17, Y=>17}, ], [ {X=>14, Y=>15}, {X=>15, Y=>16}, {X=>16, Y=>17}, {X=>17, Y=>18}, {X=>18, Y=>19}, {X=>19, Y=>20}, ], ); my @ends = sort{ $b->[0]{X} <=> $a->[0]{X} || $b->[0]{Y} <=> $a->[0]{Y} || $b->[2] cmp $a->[2] } map{ [$_->[0], $_, 'S'], [$_->[-1], $_, 'E'] } @data; my @merged = mapAdjPairs{ if ($a->[2] eq 'S') { # $a is a start point if ( $b->[2] eq 'E' and $a->[0]{X} == $b->[0]{X} # Introduce FP fudge factor if needed and $a->[0]{Y} == $b->[0]{Y} ) { # $b is and end and we found a coincident end/start pair push @{ $b->[1] }, @{ $a->[1] }[1.. $#{$a->[1]} ]; return; # we merged two sections so don't add to result } else { # We have a start point and didn't merge so add to the results return $a->[1]; } } return; } @ends, $ends[0]; # Note: repeat the first element as the last to complete the cycle # Display the results. print qq[ @{[ map{ qq[ @{[ %$_ ]} ] } @$_ ]} ] for @merged; __END__ c:\test>240810 X 11 Y 12 X 12 Y 13 X 13 Y 14 X 14 Y 15 X 15 Y 16 X 16 Y 17 X 17 Y 18 X 18 Y 19 X 19 Y 20 X 10 Y 10 X 11 Y 11 X 12 Y 12 X 13 Y 13 X 14 Y 14 X 15 Y 15 X 16 Y 16 X 17 Y 17 X 18 Y 18 X 19 Y 19 X 20 Y 20 X 21 Y 21 X 22 Y 22 X 23 Y 23 X 24 Y 24 X 1 Y 2 X 1 Y 3 X 1 Y 4