Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Re^2: Converting python list range expressions to perl

by ibm1620 (Hermit)
on Dec 04, 2022 at 17:13 UTC ( [id://11148550]=note: print w/replies, xml ) Need Help??


in reply to Re: Converting python list range expressions to perl
in thread Converting python list range expressions to perl

Ken, thanks for your writeup, including forcing me to learn a bit about Test -- I needed that! :-)

I'd rather stick with Perl's slice capability since it reads more cleanly (to me, anyway) and doesn't require copying and modifying the source array. Here's how I ended up implementing and testing pyrange():

#!/usr/bin/env perl use v5.36; use constant { AREF => 0, PYTHON => 1, EXP => 2, }; use Test::More; my @test_array = 'a' .. 'g'; my @tests = ( [\@test_array, '[:3]', 'abc'], [\@test_array, '[:-3]', 'abcd'], [\@test_array, '[3:]', 'defg'], [\@test_array, '[-3:]', 'efg'], [\@test_array, '[-3:-1]', 'ef'], # testing double-ended ranges [\@test_array, '[-3:-3]', ''], [\@test_array, '[3:-1]', 'def'], ); plan tests => 0+@tests; for my $test (@tests) { is get_array_slice_by_python_expr($test->@[AREF, PYTHON]), $test->[EXP], "Testing: $test->[PYTHON]"; } sub get_array_slice_by_python_expr ($aref, $python) { ### $re modified to return undef instead of '' when endpoint omitt +ed state $re = qr{^ \[ ( -? \d+ )? : ( -? \d+ )? \] $}x; my ($start, $stop) = $python =~ $re; my $range_aref = pyrange($aref, $start, $stop); return join '', @$range_aref; } sub pyrange($aref, $start=undef, $stop=undef) { if (!defined $start) { $start = 0; } elsif ($start < 0) { $start = @$aref + $start; } if (!defined $stop) { $stop = $#$aref; } elsif ($stop >= 0) { $stop = $stop - 1; } else { $stop = @$aref + $stop - 1; } return [@$aref[$start .. $stop]]; }
Output:
$ ./test 1..7 ok 1 - Testing: [:3] ok 2 - Testing: [:-3] ok 3 - Testing: [3:] ok 4 - Testing: [-3:] ok 5 - Testing: [-3:-1] ok 6 - Testing: [-3:-3] ok 7 - Testing: [3:-1]

Replies are listed 'Best First'.
Re^3: Converting python list range expressions to perl
by kcott (Archbishop) on Dec 04, 2022 at 18:45 UTC
    "Ken, thanks for your writeup, including forcing me to learn a bit about Test -- I needed that! :-)"

    You're welcome. It's good to be able to start a script with use v5.36;.

    "I'd rather stick with Perl's slice capability since it reads more cleanly (to me, anyway) ..."

    What you choose is entirely up to you. This correlation stood out for me:

    PythonPerl
    [OFFSET:LENGTH]splice ARRAY, OFFSET, LENGTH
    [:LENGTH]splice ARRAY, 0, LENGTH
    [OFFSET:]splice ARRAY, OFFSET
    [:]splice ARRAY, 0
    "... and doesn't require copying and modifying the source array."

    The source array, @test_array, is not modified at all. The temporary copy, @temp_array, is modified in the last statement of (my) get_array_slice_by_python_expr() function; it's then immediately discarded as it goes out of scope.

    I added your three new tests, plus a fourth ([:]), to my original code:

    [\@test_array, '[-3:-1]', 'ef'], [\@test_array, '[-3:-3]', ''], [\@test_array, '[3:-1]', 'def'], [\@test_array, '[:]', 'abcdefg'],

    All pass:

    1..8 ok 1 - Testing: [:3] ok 2 - Testing: [:-3] ok 3 - Testing: [3:] ok 4 - Testing: [-3:] ok 5 - Testing: [-3:-1] ok 6 - Testing: [-3:-3] ok 7 - Testing: [3:-1] ok 8 - Testing: [:]

    — Ken

      I didn't mean that @test_array was modified; I meant that splice() modifies its argument array, requiring a temp copy be made. It just seemed wasteful to copy an array, and modify it, and then dispose of it, when Perl slice doesn't do so. Of course, that's pure guesswork on my part - and I haven't attempted to time it.

      In your representation of Python vs Perl slicing & splicing, I didn't understand your notation OFFSET:LENGTH for Python. Python slices are OFFSET:OFFSET. (Which is why Perl slices seemed a better fit to me.) Could you clarify?

        OFFSET:LENGTH vs. OFFSET:OFFSET may be purely semantics. The relationship that I showed in the table is exactly the way I coded it in my script. Can you come up with any new tests which aren't successful?

        — Ken

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (7)
As of 2024-04-19 16:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found