Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Assign multiple items into an array containing the range operator from a file

by george59 (Initiate)
on Oct 19, 2021 at 15:26 UTC ( [id://11137734]=perlquestion: print w/replies, xml ) Need Help??

george59 has asked for the wisdom of the Perl Monks concerning the following question:

Is it possible to read a set of values that include the range operator into an array for further processing or is this disallowed - if so can anyone suggest a workaround as the array set and number of ranges is dynamic and cannot be set directly

Directly writing the ranges into an array works

!/usr/bin/perl use strict; use warnings; my @list = ([0..1], [2..4], [5..8]); my @sets = []; for my $eacharray (@list) { @sets = map { my @prev = @$_; map [ @prev, $_ ], @$eacharray } @sets +; } use Data::Dump 'dd'; dd @sets;

Writing the ranges into an array from a file doesn't

!/usr/bin/perl use strict; use warnings; open my $handle, 'input.txt'; open my $handle, '<', 'input.txt'; chomp(my @list = <$handle>); close $handle; my @sets = []; for my $eacharray (@list) { @sets = map { my @prev = @$_; map [ @prev, $_ ], @$eacharray } @sets +; } use Data::Dump 'dd'; dd @sets; The input.txt file is: [0..1] [2..4] [5..8]

Replies are listed 'Best First'.
Re: Assign multiple items into an array containing the range operator from a file
by choroba (Cardinal) on Oct 19, 2021 at 15:41 UTC
    Use a regex to extract the range edges from each line, then use the range operator to turn them into a sequence:
    #!/usr/bin/perl use warnings; use strict; my @sets = []; while (my $line = <DATA>) { if ($line =~ /\[([0-9]+)\.\.([0-9]+)\]/) { my ($from, $to) = ($1, $2); $line = [$from .. $to]; } else { chomp $line; $line = [$line]; } @sets = map { my @prev = @$_; map [ @prev, $_ ], @$line } @sets; } use Data::Dump 'dd'; dd @sets; __DATA__ [0..1] [2..4] 9 [5..8]

    Updated: missing $line in chomp, ThanX LanX.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Assign multiple items into an array containing the range operator from a file
by haukex (Archbishop) on Oct 19, 2021 at 17:43 UTC

    This seems quite similar to the recent thread loop iterator in a string, probably some of the answers there will be useful to you.

Re: Assign multiple items into an array containing the range operator from a file
by tybalt89 (Monsignor) on Oct 19, 2021 at 17:24 UTC
    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11137734 use warnings; my $inputfile = <<END; [0..1] [2..4] 9 [5..8] END open my $fh, '<', \$inputfile or die; # FIXME to your file local $/; my @sets = map { /\[(\d+)\.\.(\d+)\]/ ? $1 .. $2 : $_ } split ' ', <$f +h>; use Data::Dump 'dd'; dd \@sets;

    Outputs:

    [0 .. 4, 9, 5 .. 8]
Re: Assign multiple items into an array containing the range operator from a file
by kcott (Archbishop) on Oct 19, 2021 at 15:57 UTC

    G'day george59,

    Welcome to the Monastery.

    I added an extra line to your input file. This tests that non-sequential ranges and numbers with more than one digit work correctly.

    $ cat pm_11137734_input.txt [0..1] [2..4] [5..8] [10..13]

    Here's the code I used:

    #!/usr/bin/env perl use strict; use warnings; use autodie; my $infile = 'pm_11137734_input.txt'; my @values; my $re = qr{^\[(\d+)\.\.(\d+)\]$}; { open my $fh, '<', $infile; /$re/ && push @values, $1 .. $2 while <$fh>; } # For demo purposes only: use Data::Dump; dd \@values;

    Output:

    [0 .. 8, 10 .. 13]

    You have some strange code related to I/O and no error checking. See how I've used open and autodie.

    — Ken

Re: Assign multiple items into an array containing the range operator from a file
by AnomalousMonk (Archbishop) on Oct 20, 2021 at 06:16 UTC

    This is a variation on choroba's solution. It's intended to illustrate how factoring regexes can make it easier to support more complex and changing requirements. (Note that the RX_RANGE_1 and RX_RANGE_2 regexes can be combined into a single regex and likewise RX_DATUM_1 and RX_DATUM_2, although arguably this makes them a bit more messy.) Some data validation is done as well. This code is minimally tested.

    Win8 Strawberry 5.8.9.5 (32) Wed 10/20/2021 0:12:06 C:\@Work\Perl\monks >perl use warnings; use strict; use autodie; use Data::Dump 'dd'; my $data = <<'EOD'; [0..1] # ignore comment [9] # and blank lines [ 2 - 4 ] 87 11..14 EOD use constant RX_IGNORE => qr{ \A \s* (?: [#] [^\n]*)? \Z }xms; use constant RX_RANGE_1 => qr{ \A \s* \[ \s* (\d+) \s* (?: \.\. | -) \s* (\d+) \s* \] \s* \Z }xms; use constant RX_RANGE_2 => qr{ \A \s* (\d+) \s* (?: \.\. | -) \s* (\d+) \s* \Z }xms; use constant RX_DATUM_1 => qr{ \A \s* (\d+) \s* \Z }xms; use constant RX_DATUM_2 => qr{ \A \s* \[ \s* (\d+) \s* \] \s* \Z }xms; open my $fh, '<', \$data; my @permutations = []; LINE: while (my $line = <$fh>) { next LINE if $line =~ RX_IGNORE; # ignore blank/comment lines my @range = $line =~ RX_RANGE_1 ? ($1, $2) : # e.g. '[1..23]' or '[1-23]' $line =~ RX_RANGE_2 ? ($1, $2) : # e.g. '1..23' or '1-23' $line =~ RX_DATUM_1 ? ($1, $1) : # e.g. '23' $line =~ RX_DATUM_2 ? ($1, $1) : # e.g. '[23]' die "bad line '$line'" # default ; die "bad range: $range[0] > $range[1]: '$line'" if $range[0] > $range[1]; @permutations = map { my @prev = @$_; map [ @prev, $_ ], $range[0] .. $range[1]; } @permutations ; } # end while LINE close $fh; dd \@permutations; ^Z [ [0, 9, 2, 87, 11], [0, 9, 2, 87, 12], [0, 9, 2, 87, 13], [0, 9, 2, 87, 14], [0, 9, 3, 87, 11], [0, 9, 3, 87, 12], [0, 9, 3, 87, 13], [0, 9, 3, 87, 14], [0, 9, 4, 87, 11], [0, 9, 4, 87, 12], [0, 9, 4, 87, 13], [0, 9, 4, 87, 14], [1, 9, 2, 87, 11], [1, 9, 2, 87, 12], [1, 9, 2, 87, 13], [1, 9, 2, 87, 14], [1, 9, 3, 87, 11], [1, 9, 3, 87, 12], [1, 9, 3, 87, 13], [1, 9, 3, 87, 14], [1, 9, 4, 87, 11], [1, 9, 4, 87, 12], [1, 9, 4, 87, 13], [1, 9, 4, 87, 14], ]


    Give a man a fish:  <%-{-{-{-<

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11137734]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2024-04-24 07:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found