How to get the string Cartesian Products of 2 list

X

xueweizhong

Give 2 string list such as: a..b and 1..3, i want to get a list which
is (a1, a2, a3, b1, b2, b3). Is there an elegant way in perl to
fullfill this withou using loop BLOCK? Or Is there a elegant one line
expression to get this?
 
B

Ben Morrow

Quoth (e-mail address removed):
Give 2 string list such as: a..b and 1..3, i want to get a list which
is (a1, a2, a3, b1, b2, b3). Is there an elegant way in perl to
fullfill this withou using loop BLOCK? Or Is there a elegant one line
expression to get this?

I don't know whether you count this as using a loop (it does, of course,
underneath; but you can't possibly avoid that at some level)

use List::MoreUtils qw/pairwise/;

my @letters = (a..b);
my @numbers = (1..3);

print for pairwise { "$a$b" } @letters, @numbers;

You have to put the lists into arrays so Perl can tell which items
belong to which list.

Ben
 
X

xueweizhong

Finally i got this one on bash3.0:

print qx'bash -c "echo {1..3}{a..c}"'

Perl is the glue language and there are more than one way to do it:)
 
L

Lars Haugseth

Give 2 string list such as: a..b and 1..3, i want to get a list which
is (a1, a2, a3, b1, b2, b3). Is there an elegant way in perl to
fullfill this withou using loop BLOCK? Or Is there a elegant one line
expression to get this?

$ perl -le '@list = glob "{a,b}{1,2,3}"; print join(",", @list);'
a1,a2,a3,b1,b2,b3
 
M

Michele Dondi

Finally i got this one on bash3.0:

print qx'bash -c "echo {1..3}{a..c}"'

Perl is the glue language and there are more than one way to do it:)

Perl does glob() espansion too.


Michele
 
X

xueweizhong

Hi Michele,

perl glob in perl5.8 is not power enough than the bash3.0 glob, it
doesn't support .. operator which is fatal to this issue:

#!/bin/perl

sub X {split / /,qx/bash -c "echo @_"/}

print "glob:\n";
print join "\n", glob "{a..b}{1..2}";

print "\n\nX:\n";
print join "\n", X "{a..b}{1..2}";

glob:
a..b1..2

X:
a1
a2
b1
b2
 
L

Lars Haugseth

Hi Michele,

perl glob in perl5.8 is not power enough than the bash3.0 glob, it
doesn't support .. operator which is fatal to this issue:

Why? In practice, the lists being globbed are likely to be variables,
not hard coded inside the glob call.

{
local $" = ','; # List separator

my @letters = 'a'..'c';
my @numbers = 1..3;

my @globbed = glob "{@letters}{@numbers}";

print "@globbed\n";
}

Highly preferrable to forking a new shell process.
 
B

brian d foy

Give 2 string list such as: a..b and 1..3, i want to get a list which
is (a1, a2, a3, b1, b2, b3). Is there an elegant way in perl to
fullfill this withou using loop BLOCK? Or Is there a elegant one line
expression to get this?

Although you've already said that you don't want non-core modules,
Set::CrossProduct can help here. It wouldn't be useful for this trivial
example, but for large sets it comes in handy. It provides an iterator
to get the next item so you don't have to compute the entire list at
once.

Good luck, :)
 
X

xueweizhong

perl glob in perl5.8 is not power enough than the bash3.0 glob, it
Why? In practice, the lists being globbed are likely to be variables,
not hard coded inside the glob call.

{
local $" = ','; # List separator

my @letters = 'a'..'c';
my @numbers = 1..3;

my @globbed = glob "{@letters}{@numbers}";

print "@globbed\n";

}
I do think these lines are worse than using loop BLOCK. What I want is
an single expression, not statements with so many nosiy lines.
 
X

xueweizhong

Hi brian,
Although you've already said that you don't want non-core modules,
Set::CrossProduct can help here. ...

Really cool. I'll study it.

BTW, bash is more common than non-standard perl module, right? :)

-Todd
 
M

Michele Dondi

Really cool. I'll study it.

BTW, bash is more common than non-standard perl module, right? :)

It depends... what if you want your program to run under Windows as
well? Of course Win32 ports of bash do exist. But would you expect
people to install one for a single line in your script?


Michele
 
B

Ben Morrow

Quoth (e-mail address removed):
Really cool. I'll study it.

BTW, bash is more common than non-standard perl module, right? :)

Depending on your frame of reference, maybe. However, if you package up
your Perl program properly (see perlnewmod), you can get perl to install
modules for you automatically, which is rather harder to arrange for
bash. :)

Ben
 
L

Lars Haugseth

I do think these lines are worse than using loop BLOCK. What I want is
an single expression, not statements with so many nosiy lines.

Err, what do you mean? The only "extra" statement here is the setting
of $" to make the glob and print more readable. The rest is assignments
and output, just there to make the example complete. How would you have
done this using loops with less expressions?
 
X

xhoster

Hi brian,


Really cool. I'll study it.

BTW, bash is more common than non-standard perl module, right? :)

Apparently "bash3.0" isn't common enough. All the machines I've looked
at, many fairly new, don't have it. And on those versions, ".."
is just literal.


Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
T

Ted Zlatanov

x> I do think these lines are worse than using loop BLOCK. What I want is
x> an single expression, not statements with so many nosiy lines.

What you perceive as noise are actually good Perl programming
practices. If you don't like them, you could do:

# the original is much better code
print glob sprintf("{%s}{%s}", join(',', 'a'..'c'), join(',', 1..3));

# even more bash-like, using in-place interpolation hacks
local $" = ','; # List separator
print glob "{@{['a'..'c']}}{@{[1..3]}}\n";

You should realize that Perl is a programming language and thus does not
have all the shortcuts that bash offers. No Perl solution will satisfy
you if you just want bash. If you want bash, use bash.

Ted
 
D

Dr.Ruud

Ted Zlatanov schreef:
local $" = ','; # List separator
print glob "{@{['a'..'c']}}{@{[1..3]}}\n";

Command line version:

$perl -wle '
$"=",";
print for glob "{@{[ q{a}..q{c} ]}}{@{[ 1..3 ]}}"
'
a1
a2
a3
b1
b2
b3
c1
c2
c3
 
X

xueweizhong

Hi Ruud,

<glob "{@{[ q{a}..q{c} ]}}{@{[ 1..3 ]}}"

Really nice, a pure perl way now rather than dependant on my bash one.

After your inspiration, i get another solution using map:
perl -e 'print join ",", map { my $g=$_; map $g.$_,1..3 } "a".."c"'
a1,a2,a3,b1,b2,b3,c1,c2,c3
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top