File Coverage

blib/lib/Array/Windowed.pm
Criterion Covered Total %
statement 22 22 100.0
branch 4 4 100.0
condition n/a
subroutine 5 5 100.0
pod 1 1 100.0
total 32 32 100.0


line stmt bran cond sub pod time code
1             package Array::Windowed;
2 1     1   27228 use base qw(Exporter);
  1         4  
  1         123  
3              
4 1     1   6 use strict;
  1         2  
  1         39  
5 1     1   5 use warnings;
  1         6  
  1         31  
6              
7             #use Smart::Comments;
8 1     1   6 use List::Util qw(min max);
  1         1  
  1         807  
9              
10             our @EXPORT_OK;
11              
12             our $VERSION = "1.00";
13              
14             =head1 NAME
15              
16             Array::Windowed - return a windowed slice of the array
17              
18             =head1 SYNOPSIS
19              
20             use Array::Windowed qw(windowed_array);
21              
22             # from an array
23             my $new_array = array_window @old_array, $start_index, $count);
24              
25             # from an arrayref
26             my $new_array2 = &array_window($array_ref, $start_index, $count);
27              
28             =head1 DESCRIPTION
29              
30             Simple module to return a slice of the passed array as specified by a start
31             position and a number of elements. Unlike the built in slicing functions this
32             does not populate the returned array with Cs for out of bounds
33             operations, but simply returns a smaller array.
34              
35             =head1 FUNCTION
36              
37             Exported on demand (or you can call it fully qualified)
38              
39             =over
40              
41             =item array_windowed @old_array, $start_index, $count
42              
43             Returns an array reference containing up to C<$count> elements from the
44             C<@old_array> starting at C<$start_index>.
45              
46             Unlike a traditional array slice elements outside the bounds of the array
47             are simply dropped. Negative indexes are treated as normal indexes that
48             occur before the 0th index (rather than indexes counting backwards from
49             the start of the array.)
50              
51             This is probably best shown with a series of examples:
52              
53              
54             my @array = ['a'..'z'];
55              
56             # ["a".."z"]
57             array_windowed(@array, 0, 26);
58              
59             # ["a","b","c","d","e"]
60             array_windowed(@array, 0, 5);
61              
62             # ["b","c","d","e","f"]
63             array_windowed(@array, 1, 5);
64              
65             # []
66             array_windowed(@array, 26, 5);
67              
68             # []
69             array_windowed(@array, -50, 5);
70              
71             # ["x","y","z"]
72             array_windowed(@array, 23, 5);
73              
74             # ["a","b","c"]
75             array_windowed(@array, -2, 5);
76              
77             # ["a".."z"]
78             &array_windowed(\@array, 0, 26);
79              
80              
81             =cut
82              
83             sub array_windowed(\@$$) {
84 8     8 1 5206 my $array_ref = shift;
85 8         11 my $start = shift;
86 8         10 my $count = shift;
87              
88 8         25 my $first_index = max(0, $start);
89 8         11 my $last_index = min(@{ $array_ref } - 1, $start + $count - 1);
  8         25  
90              
91             # smart comment for debugging, uncomment use Smart::Comments above
92             ### $start
93             ### $count
94             ### $first_index
95             ### $last_index
96              
97 8 100       25 return [] if $last_index < 0;
98 7 100       17 return [] if $first_index > $last_index;
99 6         13 return [@{$array_ref}[$first_index..$last_index]];
  6         44  
100             }
101             push @EXPORT_OK, "array_windowed";
102              
103             =back
104              
105             =head1 RATIONALLE
106              
107             Why this module?
108              
109             =over
110              
111             =item Why not simple array slices with @foo[ ... ]
112              
113             Because the edge cases of indexes outside the bounds of the array don't do the
114             same thing (they return lots of Cs mainly)
115              
116             =item Why not splice?
117              
118             It's destructive on the original array.
119              
120             =item Why not Array::Window
121              
122             Because it tries too hard to DTRT, which isn't the RT for us. For example,
123             if you have a count bigger than the entire array then it always returns the
124             entire array irregardless of the start position.
125              
126             This doesn't mean it's not the module for you, however.
127              
128             =item Why not Data::Page
129              
130             This concept of windowing we're using doesn't use pages, but rather
131             a start position and a count.
132              
133             This doesn't mean it's not the module for you, however.
134              
135             =back
136              
137             =head1 AUTHOR
138              
139             Written by Mark Fowler
140              
141             =head1 COPYRIGHT
142              
143             Copyright Mark Fowler 2012. All Rights Reserved.
144              
145             This program is free software; you can redistribute it
146             and/or modify it under the same terms as Perl itself.
147              
148             =head1 BUGS
149              
150             This module does no sanity checking on the values that are passed into
151             it (i.e. it does not check that C<$start> or C<$count> are integer numbers,
152             nor does it check that the first argument is an array reference if you disable
153             prototyping.)
154              
155             Bugs should be reported via this distribution's
156             CPAN RT queue. This can be found at
157             L
158              
159             You can also address issues by forking this distribution
160             on github and sending pull requests. It can be found at
161             L
162              
163             =head1 SEE ALSO
164              
165             L, L
166              
167             =cut
168              
169             1;
170