File Coverage

blib/lib/Array/OverlapFinder.pm
Criterion Covered Total %
statement 58 58 100.0
branch 15 16 93.7
condition 3 3 100.0
subroutine 7 7 100.0
pod 2 2 100.0
total 85 86 98.8


line stmt bran cond sub pod time code
1             package Array::OverlapFinder;
2              
3             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
4             our $DATE = '2021-01-02'; # DATE
5             our $DIST = 'Array-OverlapFinder'; # DIST
6             our $VERSION = '0.005'; # VERSION
7              
8 1     1   55894 use 5.010001;
  1         11  
9 1     1   6 use strict;
  1         1  
  1         20  
10 1     1   4 use warnings;
  1         2  
  1         33  
11              
12 1     1   6 use Exporter qw(import);
  1         1  
  1         368  
13             our @EXPORT_OK = qw(find_overlap combine_overlap);
14              
15             sub _find_or_combine_overlap {
16 28     28   45 my $action = shift;
17 28 100       62 my $opts = ref($_[0]) eq 'HASH' ? shift : {};
18 28         49 my $detail = $opts->{detail};
19 28 50       56 @_ >= 2 or die "Please supply at least two sequences";
20              
21 28         35 my @detail_res;
22             my @all_overlap_items;
23              
24 28         32 my $seq1 = shift;
25 28         31 my $num_seqs = 1;
26             SEQ:
27 28         50 while (@_) {
28 32         35 my $seq2 = shift;
29 32         34 $num_seqs++;
30              
31 32         38 my @overlap_items;
32             my $index_at_seq1;
33              
34             L1:
35 32         35 for my $i (0 .. $#{$seq1}) {
  32         66  
36 92         100 my $j = $i;
37 92   100     97 while ($j <= $#{$seq1} && ($j-$i) <= $#{$seq2}) {
  160         248  
  140         262  
38 136 100       260 if ($seq1->[$j] ne $seq2->[$j - $i]) {
39 68         106 next L1;
40             }
41 68         72 $j++;
42             }
43 24         30 @overlap_items = @{$seq1}[$i .. $#{$seq1}];
  24         50  
  24         39  
44 24         41 $index_at_seq1 = $i;
45 24         37 last L1;
46             }
47              
48 32         42 my @combined;
49 32 100       76 if (defined $index_at_seq1) {
50 24         33 @combined = (@$seq1, @{$seq2}[ ($#{$seq1} - $index_at_seq1 + 1) .. $#{$seq2} ]);
  24         45  
  24         34  
  24         28  
51             } else {
52 8         19 @combined = (@$seq1, @$seq2);
53             }
54 32         49 $seq1 = \@combined;
55              
56 32         47 push @detail_res, \@overlap_items, $index_at_seq1;
57 32         69 push @all_overlap_items, \@overlap_items;
58             } # SEQ
59              
60 28 100       47 if ($action eq 'find') {
61 14 100       20 if ($detail) {
62 7         39 return @detail_res;
63             } else {
64 7 100       10 if ($num_seqs > 2) {
65 1         7 return @all_overlap_items;
66             } else {
67 6         6 return @{ $all_overlap_items[0] };
  6         39  
68             }
69             }
70             } else {
71             # combine
72 14 100       21 if ($detail) {
73 7         42 return ($seq1, @detail_res);
74             } else {
75 7         48 return @$seq1;
76             }
77             }
78             }
79              
80 14     14 1 1028 sub find_overlap { _find_or_combine_overlap('find', @_) }
81              
82 14     14 1 2635 sub combine_overlap { _find_or_combine_overlap('combine', @_) }
83              
84             1;
85             # ABSTRACT: Find/remove overlapping items among ordered sequences
86              
87             __END__