First, extract the start and end index for each range, two numbers (end >= start) for each range. Next, see if there is any overlap. That means that the start or end index of one range is inside, or touching an end, of another range, or vice versa. Actually, testing the reverse is easier: two ranges don't overlap, if the starting index of the second range comes after the end index of the first one.
Once you identified two adjoint or overlapping ranges, merge them: start is at the lowest starting index, end is at the highest end index. Be careful to restart all tests with this new range, as the new incarnation of this range now larger than it originally was, and it could overlap with ranges it didn't even touch before.
I'll try for some code, for size. First I order the ranges according to start index. Next I compare the start index for all ranges after the current one, to see if they overlap. If they do, I incorporate it into this one, delete the other one, and start all tests again for the current range. I think that should cover it.
| Update: Don't use this code without checking out Thelonius' reply, first. He's right that there are some bugs. Out of historical interest, I won't fix them here. |
Result:my @range = ([35, 55], [50, 60], [30, 40], [60, 65], [70, 80]); @range = sort { $a->[0] <=> $b->[0] } @range; for (my $i = 0; $i < @range; $i++) { my $e = $range[$i][1]; for(my $j = $i+1; $j < @range; $j++) { unless($range[$j][0] > $e) { $e = $range[$i][1] = $range[$j][1]; splice @range, $j, 1; redo; } } } use Data::Dumper; print Dumper \@range;
which looks about right to me.$VAR1 = [ [ 30, 65 ], [ 70, 80 ] ];
In reply to Re: Overlapping portions of sub strings
by bart
in thread Overlapping portions of sub strings
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |