I’m not really a fan of nested loops, so when I need to create a list of combinations based on two or three other lists, I really miss list comprehensions1 such as those in Python.
l = [(x,y) for x in range(5) for y in range(5)]
Very elegant.
If I was using Lisp, I might use a nested mapcar.
(mapcar (lambda (out) (mapcar (lambda (in) (cons in out)) '(a b c d e))) '(1 2 3 4 5))
Perl map uses $_
so you don’t need to explicitly specify the name of the lambda parameter. How can I differentiate between the outer $_ and the inner $_?
my $outer; my @x = map { $outer = $_; (map { $outer . $_ } qw(a b c d e)) } (1..5);
Note: if you are trying to do something as simple as this, take a look at Set::CrossProduct instead.
Same concept, but this perl example is slightly nicer in my opinion, and it’s closer to the original python.
my @l = map { my $x = $_; map [$x, $_], 1 .. 5 } 1 .. 5;
You can look at List::Gen module, it has mapkey() and cartesian() functions for that.
I think that Perl needs thats feature in future.
@Naveed – oh yes, the inner map is inside the outer map’s lexical scope so it is possible to my declare the variable inside the map. That makes it a lot neater already.
@zloyrusskiy – The $_{first}, $_{second}, etc… from List::Gen looks like a good generalisation of the technique I presented in my post. It would be nice if it was available in core Perl.
I know this isn’t exactly what you asked for but I found this interesting when I discovered this feature of glob:
my @x = glob( ‘{a,b,c,d,e}{1,2,3,4,5}’ );
Hehe!
@juster, that is very clever 🙂
Hey juster, I knew about this trick in shell, but I didn’t know it worked in perl’s glob. And it’s portable too!
[…] should go where they are due: I discovered this construct while reading juster’s comment on […]
my $t = [[‘a’..’e’],[1..5]];
my @x = map { $t->[0]->[$_] => $t->[1]->[$_] } 0..$#{$t->[0]};
There might be a better way than the above, but this is an alternative.
my $x = { map { $t->[0]->[$_] => $t->[1]->[$_] } 0..$#{$t->[0]} };
#hashref
You can pass the outer $_ as a parameter to the inner map put inside a sub, and then refer the outer $_ in the inner as $_[0]:
map { qw(a b c d e) } }($_) } (1..5)
Ouch, something ate half of the perl code in my previous comment, new try
map { &{ sub { map { $_[0] . $_ } qw(a b c d e) } }($_) } (1..5)