1 package DOM::Tiny::Collection;
8 use Scalar::Util 'blessed';
10 our @EXPORT_OK = ('c');
12 sub TO_JSON { [@{shift()}] }
14 sub c { __PACKAGE__->new(@_) }
18 return $self->new(grep { defined && (ref || length) } @$self);
23 return @$self unless $cb;
25 $_->$cb($i++) for @$self;
30 my ($self, $cb) = (shift, shift);
31 return $self->[0] unless $cb;
32 return List::Util::first { $_ =~ $cb } @$self if ref $cb eq 'Regexp';
33 return List::Util::first { $_->$cb(@_) } @$self;
36 sub flatten { $_[0]->new(_flatten(@{$_[0]})) }
39 my ($self, $cb) = (shift, shift);
40 return $self->new(grep { $_ =~ $cb } @$self) if ref $cb eq 'Regexp';
41 return $self->new(grep { $_->$cb(@_) } @$self);
45 join $_[1] // '', map {"$_"} @{$_[0]};
48 sub last { shift->[-1] }
51 my ($self, $cb) = (shift, shift);
52 return $self->new(map { $_->$cb(@_) } @$self);
57 return bless [@_], ref $class || $class;
63 goto &List::Util::reduce;
66 sub reverse { $_[0]->new(reverse @{$_[0]}) }
68 sub shuffle { $_[0]->new(List::Util::shuffle @{$_[0]}) }
70 sub size { scalar @{$_[0]} }
74 return $self->new(@$self[@_]);
80 return $self->new(sort @$self) unless $cb;
85 local (*{"${caller}::a"}, *{"${caller}::b"}) = (\$a, \$b);
88 return $self->new(@sorted);
92 my ($self, $cb) = (shift, shift);
93 $_->$cb(@_) for $self;
97 sub to_array { [@{shift()}] }
100 my ($self, $cb) = (shift, shift);
102 return $self->new(grep { !$seen{$_->$cb(@_)}++ } @$self) if $cb;
103 return $self->new(grep { !$seen{$_}++ } @$self);
107 map { _ref($_) ? _flatten(@$_) : $_ } @_;
110 sub _ref { ref $_[0] eq 'ARRAY' || blessed $_[0] && $_[0]->isa(__PACKAGE__) }
118 DOM::Tiny::Collection - Collection
122 use Mojo::Collection;
124 # Manipulate collection
125 my $collection = Mojo::Collection->new(qw(just works));
126 unshift @$collection, 'it';
127 say $collection->join("\n");
130 $collection->map(sub { ucfirst })->shuffle->each(sub {
131 my ($word, $num) = @_;
135 # Use the alternative constructor
136 use Mojo::Collection 'c';
137 c(qw(a b c))->join('/')->url_escape->say;
141 L<Mojo::Collection> is an array-based container for collections.
143 # Access array directly to manipulate collection
144 my $collection = Mojo::Collection->new(1 .. 25);
145 $collection->[23] += 100;
146 say for @$collection;
150 L<Mojo::Collection> implements the following functions, which can be imported
155 my $collection = c(1, 2, 3);
157 Construct a new array-based L<Mojo::Collection> object.
161 L<Mojo::Collection> implements the following methods.
165 my $array = $collection->TO_JSON;
167 Alias for L</"to_array">.
171 my $new = $collection->compact;
173 Create a new collection with all elements that are defined and not an empty
177 Mojo::Collection->new(0, 1, undef, 2, '', 3)->compact->join(', ');
181 my @elements = $collection->each;
182 $collection = $collection->each(sub {...});
184 Evaluate callback for each element in collection or return all elements as a
185 list if none has been provided. The element will be the first argument passed
186 to the callback and is also available as C<$_>.
188 # Make a numbered list
189 $collection->each(sub {
196 my $first = $collection->first;
197 my $first = $collection->first(qr/foo/);
198 my $first = $collection->first(sub {...});
199 my $first = $collection->first($method);
200 my $first = $collection->first($method, @args);
202 Evaluate regular expression/callback for, or call method on, each element in
203 collection and return the first one that matched the regular expression, or for
204 which the callback/method returned true. The element will be the first argument
205 passed to the callback and is also available as C<$_>.
208 my $first = $collection->first(sub { $_->$method(@args) });
210 # Find first value that contains the word "mojo"
211 my $interesting = $collection->first(qr/mojo/i);
213 # Find first value that is greater than 5
214 my $greater = $collection->first(sub { $_ > 5 });
218 my $new = $collection->flatten;
220 Flatten nested collections/arrays recursively and create a new collection with
223 # "1, 2, 3, 4, 5, 6, 7"
224 Mojo::Collection->new(1, [2, [3, 4], 5, [6]], 7)->flatten->join(', ');
228 my $new = $collection->grep(qr/foo/);
229 my $new = $collection->grep(sub {...});
230 my $new = $collection->grep($method);
231 my $new = $collection->grep($method, @args);
233 Evaluate regular expression/callback for, or call method on, each element in
234 collection and create a new collection with all elements that matched the
235 regular expression, or for which the callback/method returned true. The element
236 will be the first argument passed to the callback and is also available as
240 my $new = $collection->grep(sub { $_->$method(@args) });
242 # Find all values that contain the word "mojo"
243 my $interesting = $collection->grep(qr/mojo/i);
245 # Find all values that are greater than 5
246 my $greater = $collection->grep(sub { $_ > 5 });
250 my $stream = $collection->join;
251 my $stream = $collection->join("\n");
253 Turn collection into string.
255 # Join all values with commas
256 $collection->join(', ')->say;
260 my $last = $collection->last;
262 Return the last element in collection.
266 my $new = $collection->map(sub {...});
267 my $new = $collection->map($method);
268 my $new = $collection->map($method, @args);
270 Evaluate callback for, or call method on, each element in collection and create
271 a new collection from the results. The element will be the first argument
272 passed to the callback and is also available as C<$_>.
275 my $new = $collection->map(sub { $_->$method(@args) });
277 # Append the word "mojo" to all values
278 my $mojoified = $collection->map(sub { $_ . 'mojo' });
282 my $collection = Mojo::Collection->new(1, 2, 3);
284 Construct a new array-based L<Mojo::Collection> object.
288 my $result = $collection->reduce(sub {...});
289 my $result = $collection->reduce(sub {...}, $initial);
291 Reduce elements in collection with callback, the first element will be used as
292 initial value if none has been provided.
294 # Calculate the sum of all values
295 my $sum = $collection->reduce(sub { $a + $b });
297 # Count how often each value occurs in collection
298 my $hash = $collection->reduce(sub { $a->{$b}++; $a }, {});
302 my $new = $collection->reverse;
304 Create a new collection with all elements in reverse order.
308 my $new = $collection->slice(4 .. 7);
310 Create a new collection with all selected elements.
313 Mojo::Collection->new('A', 'B', 'C', 'D', 'E')->slice(1, 2, 4)->join(' ');
317 my $new = $collection->shuffle;
319 Create a new collection with all elements in random order.
323 my $size = $collection->size;
325 Number of elements in collection.
329 my $new = $collection->sort;
330 my $new = $collection->sort(sub {...});
332 Sort elements based on return value of callback and create a new collection
335 # Sort values case-insensitive
336 my $case_insensitive = $collection->sort(sub { uc($a) cmp uc($b) });
340 $collection = $collection->tap(sub {...});
342 Alias for L<Mojo::Base/"tap">.
346 my $array = $collection->to_array;
348 Turn collection into array reference.
352 my $new = $collection->uniq;
353 my $new = $collection->uniq(sub {...});
354 my $new = $collection->uniq($method);
355 my $new = $collection->uniq($method, @args);
357 Create a new collection without duplicate elements, using the string
358 representation of either the elements or the return value of the
362 my $new = $collection->uniq(sub { $_->$method(@args) });
365 Mojo::Collection->new('foo', 'bar', 'bar', 'baz')->uniq->join(' ');
368 Mojo::Collection->new([1, 2], [2, 1], [3, 2])->uniq(sub{ $_->[1] })->to_array;
372 Report any issues on the public bugtracker.
376 Dan Book <dbook@cpan.org>
378 =head1 COPYRIGHT AND LICENSE
380 This software is Copyright (c) 2015 by Dan Book.
382 This is free software, licensed under:
384 The Artistic License 2.0 (GPL Compatible)