File Coverage

blib/lib/Array/Extract.pm
Criterion Covered Total %
statement 34 34 100.0
branch 6 8 75.0
condition n/a
subroutine 5 5 100.0
pod 1 1 100.0
total 46 48 95.8


line stmt bran cond sub pod time code
1             package Array::Extract;
2 1     1   71834 use base qw(Exporter);
  1         3  
  1         91  
3              
4 1     1   26 use 5.006;
  1         4  
  1         34  
5              
6 1     1   5 use strict;
  1         6  
  1         35  
7 1     1   5 use warnings;
  1         1  
  1         280  
8              
9             our @EXPORT_OK;
10             our $VERSION = "1.00";
11              
12             =head1 NAME
13              
14             Array::Extract - extract element from an array
15              
16             =head1 SYNOPSIS
17              
18             use Array::Extract qw(extract);
19              
20             # remove those members from @members who are
21             # blackballed and store them in @banned
22             my @banned = extract { $_->blackballed } @members;
23              
24             =head1 DESCRIPTION
25              
26             Function to extract elements from an array that match
27             a block. See L for a
28             more comprehensive example of how this can be useful
29              
30             =head2 Function
31              
32             The function is exported on demand
33              
34             =over
35              
36             =item extract BLOCK ARRAY
37              
38             Removes elements from the ARRAY that match the
39             block and returns them.
40              
41             # leave just the even numbers in @numbers
42             my @numbers = (1..100);
43             my @odds = extract { $_ % 2 } @numbers;
44              
45             Care is taken to do the least number of splice
46             operations as possible (which can be important when
47             the array is a tied object with a class such as
48             Tie::File)
49              
50             =cut
51              
52             sub extract(&\@) {
53 1     1 1 61 my $block = shift;
54 1         2 my $array = shift;
55              
56             # loop invariants. The element we're currently on
57             # and the length of the array
58 1         2 my $i = 0;
59 1         2 my $length = @{ $array };
  1         13  
60              
61             # the index we started removing from
62 1         6 my $remove_from;
63              
64             # what we've collected to return
65             my @return;
66              
67             # for each element of the array
68 1         5 while ($i < $length) {
69 6         27 local $_ = $array->[ $i ];
70 6 100       36 if (!$block->()) {
71             # this content we keep
72 2 50       12 if (defined $remove_from) {
73             # but first we need to remove the stuff we wanted
74             # to extract from the list
75 2         4 my $number = $i - $remove_from;
76 2         3 $i -= $number;
77 2         3 $length -= $number;
78 2         2 splice @{$array}, $remove_from, $number;
  2         9  
79 2         37 undef $remove_from;
80             }
81             } else {
82             # remember we're going to remove this content
83 4 100       28 $remove_from = $i
84             unless defined $remove_from;
85              
86             # remember the content we were going to keep
87 4         9 push @return, $_;
88             }
89 6         17 $i++;
90             }
91              
92             # remove any thing at the end of the list that we were still removing
93 1 50       12 splice @{$array}, $remove_from, $i - $remove_from if defined $remove_from;
  1         5  
94 1         18 return @return;
95             }
96             push @EXPORT_OK, "extract";
97              
98             =back
99              
100             =head1 AUTHOR
101              
102             Written by Mark Fowler
103              
104             =head1 COPYRIGHT
105              
106             Copyright Mark Fowler 2011. All Rights Reserved.
107              
108             This program is free software; you can redistribute it
109             and/or modify it under the same terms as Perl itself.
110              
111             =head1 BUGS
112              
113             This module (deliberately) does not alias C<$_> to the
114             actual array element within the block
115              
116             Bugs should be reported via this distribution's
117             CPAN RT queue. This can be found at
118             L
119              
120             You can also address issues by forking this distribution
121             on github and sending pull requests. It can be found at
122             L
123              
124             =head1 SEE ALSO
125              
126             L L, L, L
127              
128             =cut
129              
130             1;