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

Dear Monks,

I have written a sub to decode a sting of information from a 15 character base 36 input. I haven't tested it yet, however I believe it should work. My question is, where I have it splitting the data via substr as 5 separate lines, is there a simpler way of doing this, like splitting it into an array with a regular expression? It ends up returning it as an array anyway so if I can skip making the array that would be great.

My includes for reference:
use strict; use warnings; use POSIX; use DBI; use Crypt::Eksblowfish::Bcrypt qw(bcrypt_hash); use Math::BaseCalc;
And the sub in question:
sub ReadDaycode { # Get daycode. my $DC = $_[0]; # Divide daycode into its parts my $BoardTotal = $B10->to_base(substr($DC,0,4)); my $AvgSample = $B10->to_base(substr($DC,4,2)); my $Level = $B10->to_base(substr($DC,6,2)); my $Exp = $B10->to_base(substr($SC,8,5)); my $Fails = $B10->to_base(substr($DC,13,2)); return ($BoardTotal,$AvgSample,$Level,$Exp,$Fails); }
Thankyou all for your help :)

Replies are listed 'Best First'.
Re: Dividing a string into multiple substrings of different length
by BrowserUk (Patriarch) on Jan 04, 2015 at 05:37 UTC

    This:

    my $BoardTotal = $B10->to_base(substr($DC,0,4)); my $AvgSample = $B10->to_base(substr($DC,4,2)); my $Level = $B10->to_base(substr($DC,6,2)); my $Exp = $B10->to_base(substr($SC,8,5)); my $Fails = $B10->to_base(substr($DC,13,2));

    Can also be done like this:

    my( $BoardTotal, $AvgSample, $Level, $Exp, $Fails ) = map $B10->to_bas +e( $_ ), unpack 'A4 A2 A2 A5 A2', $DC;

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Dividing a string into multiple substrings of different length
by Anonymous Monk on Jan 04, 2015 at 07:20 UTC
    is there a simpler way of doing this, like splitting it into an array with a regular expression?
    Actually yes, this is possible with a regular expression.
    my ($board_total, etc...) = map $B10->to_base($_), $DC =~ /(....)(..)(..)(.....)(..)/;
    perlop: If the "/g" option is not used, "m//" in list context returns a list consisting of the subexpressions matched by the parentheses in the pattern, that is, ($1, $2, $3...)
Re: Dividing a string into multiple substrings of different length
by AnomalousMonk (Archbishop) on Jan 04, 2015 at 19:21 UTC

    The unpack approach used by BrowserUk above is IMHO quite elegant and attractive, not to mention efficient, but a regex-extraction approach offers one further possible advantage: data validation.

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my $s = 'abcdefghijklmno'; ;; my $validate = qr{ \A (....) (..) (..) (.....) (..) \z }xms; ;; my @ra = Suc($s, $validate); dd \@ra; ;; sub Suc { my ($DC, $rx_valid) = @_; ;; my @ra = $DC =~ $rx_valid; @ra or die qq{bad format: '$DC'}; ;; return map uc($_), @ra; } " ["ABCD", "EF", "GH", "IJKLM", "NO"]
    Here, the validation/extraction regex is defined separately and passed to the function. Rather than the dummy used in the example code, it can be highly specific to the data. One can imagine a further elaboration in which the passed regex is optional and a default regex is used in the subroutine if no regex is passed:
        my ($DC, $rx_valid) = @_;
        $rx_valid //= qr{ \A default pattern \z }xms;


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

Re: Dividing a string into multiple substrings of different length
by nlwhittle (Beadle) on Jan 04, 2015 at 16:42 UTC

    One minor side point: the "generally accepted, Perl-ish" way to get the argument(s) in your sub would be:

    my $DC = shift;

    which is equivalent to:

    my $DC = shift @_;

    Your code is ok, but Perl was designed to help you avoid having to use "ugly" array index notation. If you look at much Perl code going forward, you are likely to see this type of thing expressed with the "shift" operator much more often than the way you have it written.

    --Nick
A reply falls below the community's threshold of quality. You may see it by logging in.