File Coverage

blib/lib/SHARYANTO/List/Util.pm
Criterion Covered Total %
statement 62 80 77.5
branch 18 30 60.0
condition 36 93 38.7
subroutine 10 14 71.4
pod 11 11 100.0
total 137 228 60.0


line stmt bran cond sub pod time code
1             package SHARYANTO::List::Util;
2              
3             our $DATE = '2015-09-04'; # DATE
4             our $VERSION = '0.77'; # VERSION
5              
6 1     1   19483 use 5.010;
  1         4  
7 1     1   5 use strict;
  1         1  
  1         20  
8 1     1   5 use warnings;
  1         1  
  1         864  
9              
10             require Exporter;
11             our @ISA = qw(Exporter);
12             our @EXPORT_OK = qw(
13             uniq_adj uniq_adj_ci uniq_ci
14             find_missing_nums_in_seq
15             find_missing_strs_in_seq
16             max_in_range maxstr_in_range
17             min_in_range minstr_in_range
18             pick pick_n
19             );
20              
21             # TODO: minmaxstr (not included in List::MoreUtils)
22             # TODO: minmax_in_range. minmaxstr_in_range
23             # TODO: *_in_xrange
24             # TODO? pick_n_distinct
25              
26             sub uniq_adj {
27 2     2 1 3771 my @res;
28              
29 2 50       10 return () unless @_;
30 2         4 my $last = shift;
31 2         4 push @res, $last;
32 2         7 for (@_) {
33 12 0 33     30 next if !defined($_) && !defined($last);
34             # XXX $_ becomes stringified
35 12 100 33     95 next if defined($_) && defined($last) && $_ eq $last;
      66        
36 10         18 push @res, $_;
37 10         24 $last = $_;
38             }
39 2         26 @res;
40             }
41              
42             sub uniq_adj_ci {
43 1     1 1 3 my @res;
44              
45 1 50       6 return () unless @_;
46 1         2 my $last = shift;
47 1         3 push @res, $last;
48 1         3 for (@_) {
49 6 0 33     17 next if !defined($_) && !defined($last);
50             # XXX $_ becomes stringified
51 6 100 33     49 next if defined($_) && defined($last) && lc($_) eq lc($last);
      66        
52 4         9 push @res, $_;
53 4         7 $last = $_;
54             }
55 1         10 @res;
56             }
57              
58             sub uniq_ci {
59 1     1 1 2337 my @res;
60              
61             my %mem;
62 1         4 for (@_) {
63 7 100       31 push @res, $_ unless $mem{lc $_}++;
64             }
65 1         9 @res;
66             }
67              
68             sub find_missing_nums_in_seq {
69 1     1 1 2351 require List::Util;
70              
71 1         3 my @res;
72 1         15 my $min = List::Util::min(@_);
73 1         5 my $max = List::Util::max(@_);
74              
75 1         3 my %h = map { $_=>1 } @_;
  7         20  
76 1         5 for ($min..$max) {
77 8 100       28 push @res, $_ unless $h{$_};
78             }
79 1 50       11 wantarray ? @res : \@res;
80             }
81              
82             sub find_missing_strs_in_seq {
83 1     1 1 2265 require List::Util;
84              
85 1         2 my @res;
86 1         14 my $min = List::Util::minstr(@_);
87 1         4 my $max = List::Util::maxstr(@_);
88              
89 1         3 my %h = map { $_=>1 } @_;
  3         12  
90 1         5 for ($min..$max) {
91 5 100       23 push @res, $_ unless $h{$_};
92             }
93 1 50       11 wantarray ? @res : \@res;
94             }
95              
96             sub max_in_range {
97 6     6 1 2485 my $lower = shift;
98 6         27 my $upper = shift;
99              
100 6         9 my $ans;
101 6         16 for (@_) {
102 30 100 100     292 $ans = $_ if defined($_) &&
      33        
      100        
      66        
      100        
      66        
103             (!defined($ans) || $ans < $_) &&
104             (!defined($lower) || $lower <= $_) &&
105             (!defined($upper) || $upper >= $_);
106             }
107 6         26 $ans;
108             }
109              
110             sub maxstr_in_range {
111 0     0 1 0 my $lower = shift;
112 0         0 my $upper = shift;
113              
114 0         0 my $ans;
115 0         0 for (@_) {
116 0 0 0     0 $ans = $_ if defined($_) &&
      0        
      0        
      0        
      0        
      0        
117             (!defined($ans) || $ans lt $_) &&
118             (!defined($lower) || $lower le $_) &&
119             (!defined($upper) || $upper ge $_);
120             }
121 0         0 $ans;
122             }
123              
124             sub min_in_range {
125 7     7 1 2126 my $lower = shift;
126 7         12 my $upper = shift;
127              
128 7         9 my $ans;
129 7         22 for (@_) {
130 35 100 100     372 $ans = $_ if defined($_) &&
      33        
      100        
      66        
      100        
      66        
131             (!defined($ans) || $ans > $_) &&
132             (!defined($lower) || $lower <= $_) &&
133             (!defined($upper) || $upper >= $_);
134             }
135 7         27 $ans;
136             }
137              
138             sub minstr_in_range {
139 0     0 1   my $lower = shift;
140 0           my $upper = shift;
141              
142 0           my $ans;
143 0           for (@_) {
144 0 0 0       $ans = $_ if defined($_) &&
      0        
      0        
      0        
      0        
      0        
145             (!defined($ans) || $ans gt $_) &&
146             (!defined($lower) || $lower le $_) &&
147             (!defined($upper) || $upper ge $_);
148             }
149 0           $ans;
150             }
151              
152             sub pick {
153 0     0 1   $_[@_ * rand];
154             }
155              
156             sub pick_n {
157 0     0 1   my $n = shift;
158 0           my @res;
159 0   0       while (@_ && @res < $n) {
160 0           push @res, splice(@_, @_*rand(), 1);
161             }
162 0           @res;
163             }
164              
165             1;
166             # ABSTRACT: List utilities
167              
168             __END__
169              
170             =pod
171              
172             =encoding UTF-8
173              
174             =head1 NAME
175              
176             SHARYANTO::List::Util - List utilities
177              
178             =head1 VERSION
179              
180             This document describes version 0.77 of SHARYANTO::List::Util (from Perl distribution SHARYANTO-Utils), released on 2015-09-04.
181              
182             =head1 FUNCTIONS
183              
184             Not exported by default but exportable.
185              
186             =head2 uniq_adj(@list) => LIST
187              
188             Remove I<adjacent> duplicates from list, i.e. behave more like Unix utility's
189             B<uniq> instead of L<List::MoreUtils>'s C<uniq> function, e.g.
190              
191             my @res = uniq(1, 4, 4, 3, 1, 1, 2); # 1, 4, 3, 1, 2
192              
193             =head2 uniq_adj_ci(@list) => LIST
194              
195             Like C<uniq_adj> except case-insensitive.
196              
197             =head2 uniq_ci(@list) => LIST
198              
199             Like C<List::MoreUtils>' C<uniq> except case-insensitive.
200              
201             =head2 find_missing_nums_in_seq(LIST) => LIST
202              
203             Given a list of integers, return number(s) missing in the sequence, e.g.:
204              
205             find_missing_nums_in_seq(1, 2, 3, 4, 7, 8); # (5, 6)
206              
207             =head2 find_missing_strs_in_seq(LIST) => LIST
208              
209             Like C<find_missing_nums_in_seq>, but for strings/letters "a".."z".
210              
211             find_missing_strs_in_seq("a", "e", "b"); # ("c", "d")
212             find_missing_strs_in_seq("aa".."zu", "zz"); # ("zv", "zw", "zx", "zy")
213              
214             =head2 min_in_range($lower, $upper, @list) => $num
215              
216             Find lowest number C<$num> in C<@list> which still satisfies C<< $lower <= $num
217             <= $upper >>. C<$lower> and/or C<$upper> can be undef to express no limit.
218              
219             =head2 minstr_in_range($lower, $upper, @list) => $str
220              
221             Find lowest string C<$str> in C<@list> which still satisfies C<< $lower le $x
222             le $upper >>. C<$lower> and/or C<$upper> can be undef to express no limit.
223              
224             =head2 max_in_range($lower, $upper, @list) => $num
225              
226             Find highest number C<$num> in C<@list> which still satisfies C<< $lower <= $num
227             <= $upper >>. C<$lower> and/or C<$upper> can be undef to express no limit.
228              
229             =head2 maxstr_in_range($lower, $upper, @list) => $str
230              
231             Find highest string C<$str> in C<@list> which still satisfies C<< $lower le $x
232             le $upper >>. C<$lower> and/or C<$upper> can be undef to express no limit.
233              
234             =head2 pick(@list) => $item
235              
236             Randomly pick an item from list. It is actually simply done as:
237              
238             $_[@_ * rand]
239              
240             Example:
241              
242             pick(1, 2, 3); # => 2
243             pick(1, 2, 3); # => 1
244              
245             =head2 pick_n($n, @list) => @picked
246              
247             Randomly pick C<n> different items from list. Note that there might still be
248             duplicate values in the result if the original list contains duplicates.
249              
250             pick_n(3, 1,2,3,4,5); # => (3,2,5)
251             pick_n(2, 1,2,3,4,5); # => (3,1)
252             pick_n(2, 1,1,1,1); # => (1,1)
253             pick_n(4, 1,2,3); # => (3,1,2)
254              
255             =head1 SEE ALSO
256              
257             L<SHARYANTO>
258              
259             =head1 HOMEPAGE
260              
261             Please visit the project's homepage at L<https://metacpan.org/release/SHARYANTO-Utils>.
262              
263             =head1 SOURCE
264              
265             Source repository is at L<https://github.com/perlancar/perl-SHARYANTO-Utils>.
266              
267             =head1 BUGS
268              
269             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=SHARYANTO-Utils>
270              
271             When submitting a bug or request, please include a test-file or a
272             patch to an existing test-file that illustrates the bug or desired
273             feature.
274              
275             =head1 AUTHOR
276              
277             perlancar <perlancar@cpan.org>
278              
279             =head1 COPYRIGHT AND LICENSE
280              
281             This software is copyright (c) 2015 by perlancar@cpan.org.
282              
283             This is free software; you can redistribute it and/or modify it under
284             the same terms as the Perl 5 programming language system itself.
285              
286             =cut