Preface
Goal: Continue Part One
4: List Comprehension Equivalent.
Using Map and Grep.
Perl is actually great. Although the perl syntax is not as concise as perl list comprehension, It natively has support for map, and filtering with grep.
Simple Example
Consider examine map
, applying to our songs records.
my @songs_title = map {
@$_{'title'}
} @MySongs::songs;
say join(':', @songs_title);
With the result as below:
Cantaloupe Island:Let It Be:Knockin' on Heaven's Door:Emotion:The River
And then go further with grep
.
my @songs_tags = map {
$_->{'tags'}
} grep {
exists($_->{'tags'})
} @MySongs::songs;
for my $tags ( @songs_tags ) {
say join(":", @$tags);
}
With the result as below:
60s:jazz
60s:rock
70s:rock
70s:pop
we can examine the object shown in output result above.
Flatten
With just a little modification, we can flatten the array.
use MySongs;
my @songs_tags = map {
@{ $_->{'tags'} }
} grep {
exists($_->{'tags'})
} @MySongs::songs;
say join(":", @songs_tags);
This should be, without a doubt, almost list comprehension. With the result similar as below record:
❯ ./12-flatten.pl
60s:jazz:60s:rock:70s:rock:70s:pop
Unique
And we can also chain the function, using previously grabbed code from stackoverflow.
use MySongs;
my %seen;
my @songs_tags = grep {
!$seen{$_}++
} map {
@{ $_->{'tags'} }
} grep {
exists($_->{'tags'})
} @MySongs::songs;
say join(":", @songs_tags);
With the result similar as below record:
❯ ./13-unique.pl
60s:jazz:rock:70s:pop
5: Approach in Solving Unique
A custom example, that you can rewrite.
An Algorithm Case
Why reinvent the wheel?
The same reason as any other articles.
x:xs Pattern Matching
The same with any other articles as well.
Exclude Function
The exclude
function is just a filter
with below details:
my @tags = ('rock',
'jazz', 'rock', 'pop', 'pop');
sub exclude {
my ($value, @tags) = @_;
grep(!/$value/, @tags);
}
say join(':', exclude('rock', @tags));
With the result as below array
:
❯ ./21-exclude.pl
jazz:pop:pop
Recursive Unique Function
With exclude
function above,
we can build unique
function recursively.
Since we are going to reuse the unique approach in other script. It is better to bundle the script in its own perl module.
package MyHelperUnique;
use strict;
use warnings;
sub unique {
if (@_ <= 1) {
@_;
} else {
# array[$head:@tail]
my $head = shift;
my @tail = @_;
# recursive unique
my @xcld = grep(!/$head/, @tail);
my @uniq = unique(@xcld);
# returned array
unshift @uniq, $head;
@uniq;
}
}
1;
The return values is in array.
![Perl: The Unique Function][img-my-unique-perl]
Using Unique Module
There is nothing to say in this code below.
Just apply unique
function to our song records.
use MyHelperUnique;
my @tags = ('rock',
'jazz', 'rock', 'pop', 'pop');
say join(':',
MyHelperUnique::unique(@tags));
With the result as below array
:
❯ ./22-unique-a.pl
rock:jazz:pop
Applying Unique to Songs Records
Now we can apply the method to our unique song challenge.
use MySongs;
use MyHelperFlatten;
use MyHelperUnique;
say join(':',
MyHelperUnique::unique(
MyHelperFlatten::flatten(
@MySongs::songs
)));
With the same result as below
❯ ./22-unique-b.pl
60s:jazz:rock:70s:pop
What is Next 🤔?
We have alternative way to extract the record structure. With pattern similar to list comprehension.
Consider continue reading [ Raku - Playing with Records - Part One ].