Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

split an array in two

by water (Deacon)
on Apr 28, 2005 at 02:38 UTC ( [id://452193]=perlquestion: print w/replies, xml ) Need Help??

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

This code splits an array in two. It seems ugly and long. Is there a better perl way? Not looking for golf, just looking to learn better idioms. Thanks!
sub split_array_in_two { my (@x) = @_; return ([],[]) unless @x; my $n = (scalar @x) -1; my $m = int ($n/2); return ( [ @x[0 .. $m]], [ @x[($m+1) .. $n]]); }

Replies are listed 'Best First'.
Re: split an array in two
by Zaxo (Archbishop) on Apr 28, 2005 at 02:42 UTC

    Splice:

    sub split_array_in_two { my @x = @_; my @second = splice @x, @x/2; \@x, \@second; }
    Explicitly returning empty array references is unnecessary, since an empty argument list will give you that anyway.

    After Compline,
    Zaxo

      Note that your solution divides the data differently than the OP's code. Use 1+$#x/2 instead of @x/2 to get the OP's result.

      You can also write it

      sub split_array_in_two{ \@_, [splice @_, 1+$#_/2] }

      Caution: Contents may have been coded under pressure.
Re: split an array in two
by Tommy (Chaplain) on Apr 28, 2005 at 03:47 UTC
    sub split_array_in_two {return unless @_;[splice(@_,0,(int scalar(@_)/ +2))],\@_}
    --
    Tommy Butler, a.k.a. Tommy
Re: split an array in two
by mda2 (Hermit) on Apr 28, 2005 at 04:16 UTC
    This is my code. Less var changes, more eficient (?)...
    sub split_array_in_two { my $len = int($#_/2); return unless ( @_ ); return [ @x[0..$len] ], [ @x[$len+1..$#x] ]; }
    scalar(@_) is numbered from 1 to elements... and
    $#_ is numbered from 0 to limit.

    Your code isnīt long... is readable and suficient.

      scalar(@_) is numbered from 1 to elements... and $#_ is numbered from 0 to limit.

      What do you mean? when @x is empty scalar(@x) is 0 and $#x is -1.

Re: split an array in two
by salva (Canon) on Apr 28, 2005 at 08:36 UTC
    sub split_array_in_two { ([splice @_, @_/2], \@_)[1,0] }
    or
    sub split_array_in_two { my $l=@_/2; [@_[0..$l-1]], [@_[$l..$#_]] }
    or the funny recursive way:
    sub da (\@\@\@) { my ($s, $a, $b)=@_; push(@$a, shift @$s), da(@$s, @$b, @$a) if @$s } my (@a, @b); my @s=1..7; da(@s, @a, @b); print "@a - @b\n"
Re: split an array in two
by Roy Johnson (Monsignor) on Apr 28, 2005 at 14:10 UTC
    You don't need to copy the array; creating an arrayref does that. And you can calculate the indices on the fly, so you need no temp variables or calls to splice. Just one expression:
    sub split_array_in_two { ([@_[0..$#_/2]], [@_[$#_/2+1..$#_]]); } for (0..5) { print map("<@$_>", split_array_in_two(1..$_)), "\n"; }

    Caution: Contents may have been coded under pressure.
      sub split_array_in_two{ [@_[0..@_/2-1]], [@_[@_/2..@_]] }
        You're reaching beyond the end of the array, resulting in an extra undef getting stuck on the end of your second arrayref. Also, a one element list gets replicated in both resulting arrays.

        Caution: Contents may have been coded under pressure.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (6)
As of 2024-04-23 13:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found