Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

RFC: Playing with glob

by Lady_Aleena (Curate)
on Sep 15, 2015 at 19:25 UTC ( #1142125=perlquestion: print w/replies, xml ) Need Help??
Lady_Aleena has asked for the wisdom of the Perl Monks concerning the following question:

Several weeks ago I was playing around with glob's ability to create lists from stringified lists. (The forth paragraph in the doc.) I at first wanted to see if I could feed it arrays directly, but I was shown by jeffa the lists had to be comma separated strings. After playing around with it for a few minutes, I thought about finding a way use arrays, so wrote the following.

Note: I do not like the name of the subroutine, so I am open to suggestions.

sub glob_array { my (%opt) = @_; my $joiner = $opt{'joiner'} ? $opt{'joiner'} eq ' ' ? "' '" : $opt{ +'joiner'} : ''; my $space = $opt{'space holder'} ? $opt{'space holder'} : '_'; # The arrays have to be strinified into comma separated lists. Thank + you to jeffa for showing me. my $arrays = [map { $_ = '{'.join( ',', @{$_} ).'}'; $_ =~ s/ /$spac +e/g; $_; } @{$opt{'arrays'}}]; my $string = join( $joiner, @$arrays ); my @raw_array = glob "$string"; my @array = map { $_ =~ s/$space/ /g; $_; } @raw_array; return \@array; }
  • The joiner is the character you wish to use to join the values of the arrays together. (If the joiner is a space, it has to be quoted, hence the complicated line of code for it.)
  • The space holder converts the spaces in the values into the character of your choice. Spaces in the array values will muck up your output. (Sorry I can't explain that better.)
  • The arrays are the list of array (refs) you want to use to make the list.

Here are some sample arrays and how they would look once glob has done its work.

my @colors = qw(red green blue); my @directions = qw(north south east west); my @numbers = (1..3); my $array = glob_array( 'arrays' => [\@colors, \@directions, \@numbers +], 'joiner' => ' ', 'space holder' => '__' );

Output

$VAR1 = [ 'red north 1', 'red north 2', 'red north 3', 'red south 1', 'red south 2', 'red south 3', 'red east 1', 'red east 2', 'red east 3', 'red west 1', 'red west 2', 'red west 3', 'green north 1', 'green north 2', 'green north 3', 'green south 1', 'green south 2', 'green south 3', 'green east 1', 'green east 2', 'green east 3', 'green west 1', 'green west 2', 'green west 3', 'blue north 1', 'blue north 2', 'blue north 3', 'blue south 1', 'blue south 2', 'blue south 3', 'blue east 1', 'blue east 2', 'blue east 3', 'blue west 1', 'blue west 2', 'blue west 3' ];

I have yet to figure out how to make this more interesting by including a pattern or a single joiner. From the above output, instead of plain green west 2 having green sector west tower 2nd floor or something akin to it. I could pre-munge the lists, but adding the ability to use a pattern would be nice too.

So, I would like a new name for the subroutine and maybe some pointers on how to add in a pattern to this. Also, maybe a few good reasons to use this I may not be seeing other than making a list to use for random selection.

No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
Lady Aleena

Replies are listed 'Best First'.
Re: RFC: Playing with glob
by MidLifeXis (Monsignor) on Sep 15, 2015 at 20:14 UTC

    This is basically iterating over the elements in an arbitrary number of arrays and returning all combinations of them, one from each array, correct?

    I seem to remember reading something in Higher Order Perl, and even here on PerlMonks (the node is currently eluding me) providing a solution to the iteration part of this. All that is left then is to join($delim, @selected_elements) for each set of selected elements.

    Update: Re: All Combinations of three arrays. might be an inspiration.

    --MidLifeXis

      For those who aren't aware, Higher Order Perl was made free by its author Mark Jason Dominus. It's a fantastic book, and a must read for those wanting to learn some of the more advanced concepts in Perl.

Re: RFC: Playing with glob
by jeffa (Bishop) on Sep 15, 2015 at 22:48 UTC

    A google search for "perl combinations and permutations" yielded Permutations and combinations. Since you are creating permutations of the given arrays, the name of the subroutine should probably be permute:

    print "[", join(", ", @$_), "]\n" for permute( [qw( red green blue )], [qw( north south east west )], [1 .. 3], ); # authored by merlyn sub permute { my $last = pop @_; unless (@_) { return map [$_], @$last; } return map { my $left = $_; map [@$left, $_], @$last } permute(@_); } __DATA__ [red, north, 1] [red, north, 2] [red, north, 3] [red, south, 1] [red, south, 2] [red, south, 3] [red, east, 1] [red, east, 2] [red, east, 3] [red, west, 1] [red, west, 2] [red, west, 3] [green, north, 1] [green, north, 2] [green, north, 3] [green, south, 1] [green, south, 2] [green, south, 3] [green, east, 1] [green, east, 2] [green, east, 3] [green, west, 1] [green, west, 2] [green, west, 3] [blue, north, 1] [blue, north, 2] [blue, north, 3] [blue, south, 1] [blue, south, 2] [blue, south, 3] [blue, east, 1] [blue, east, 2] [blue, east, 3] [blue, west, 1] [blue, west, 2] [blue, west, 3]

    As you can see, his method returns a list of permutations, and each permutation is contained inside an array reference. By doing this, he has deferred the decision of formatting the output to the client and he does not have to worry about that portion of the code, which has been distilled to a simple print "[", join(", ", @$_), "]\n" for permute().

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    

      permute! Thank you for the much better name for the subroutine!

      I was not looking for the best way to get all the permutations of the combinations of the arrays, I was seeing how that aspect of glob worked then fiddling with it. I first looked at glob for the file listing ability, then saw its ability to permute through several strings to make interesting lists and decided to play with it.

      I am still interested in finding a way to incorporate a pattern into either to reduce the steps to getting the list of values.

      Thank you for stopping by.

      No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
      Lady Aleena
Re: RFC: Playing with glob
by Anonymous Monk on Sep 15, 2015 at 23:21 UTC

    Who needs glob? It's almost a one-liner.

    Toss out space holder, it's not needed, and use $" for the joiner string since it's already used for that :)
    (local $" = "somejoiner" if you want to).

    #!/usr/bin/perl # http://perlmonks.org/?node_id=1142125 use strict; use warnings; sub glob_array { my @ans = @{pop()}; @ans = map{ my $i = $_; map $i.$".$_, @ans } @{pop()} while @_; \@ans; } my @colors = qw(red green blue); my @directions = qw(north south east west); my @numbers = (1..3); my $array = glob_array( \@colors, \@directions, \@numbers ); use Data::Dump 'pp'; pp $array;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1142125]
Approved by Old_Gray_Bear
Front-paged by Old_Gray_Bear
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (11)
As of 2017-05-25 17:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?