Re (tilly) 1: interleave two arrays
by tilly (Archbishop) on Feb 03, 2001 at 04:57 UTC
|
| [reply] |
|
Yes, I realize that. This came out of my toying with functional programming in perl. Most of the other solutions I've seen here have side effects that I was trying (for intellectual, rather than practical reasons) to avoid.
| [reply] |
|
| [reply] |
Re: interleave two arrays
by runrig (Abbot) on Feb 03, 2001 at 02:30 UTC
|
my @interleave = mapcar { @_ } \@list1, \@list2, \@list3;
| [reply] [d/l] |
Re: interleave two arrays
by Fastolfe (Vicar) on Feb 03, 2001 at 02:34 UTC
|
This is also something that's come up in SOPW a few times. The most recent, interleaving lists, has some alternative implementations for those that are curious. | [reply] |
Re: interleave two arrays
by gryng (Hermit) on Feb 03, 2001 at 02:43 UTC
|
sub interleave {
my $y;
while (@{ $_[0] } or @{ $_[1] }) {
push @$y, shift @{ $_[0] } if @{ $_[0] };
push @$y, shift @{ $_[1] } if @{ $_[1] };
}
return $y;
}
Ack, what have I done, this will surely lead to endless perl golf!
Ciao,
Gryn
Update: Eek, this doesn't work. Please ignore -- I'm at work and will be a while to fix.
Update: Ok that seems better. Thank you for your patience :) | [reply] [d/l] |
Re: interleave two arrays
by scott (Chaplain) on Feb 04, 2001 at 04:15 UTC
|
Shockingly (for me to see this question here), I just
solved this problem two days ago.
Try this:
@foo = ( 1 , 3 , 5 , 7 );
@bar = ( 2 , 4 , 6 , 8 );
@baz = map { ( $_ , shift @bar ) } @foo;
It suffers from losing the end of @bar
if length( @bar ) > length ( @foo )
though.
| [reply] [d/l] [select] |
|
Scott,
I tried your code on a similar problem that I had
print STDOUT my @foobar = map { ( $_, shift @foo ) } @bar;
and it worked, but when I turn on use warnings; I get the following error:
Use of uninitialized value in print at line 3
I've done some research and it seems that some people just complain about using warning and turn them off (I don't want to do that), and other say to re-work the code into a while loop.
Anyone have any advice as to how I can keep the code while getting rid of the error?
| [reply] [d/l] [select] |
|
use strict;
use warnings;
my @foo = ( 1 , 3 , 5 , 7 );
my @bar = ( 2 , 4 , 6 , 8 );
print STDOUT my @baz = map { ( $_ , shift @bar ) } @foo;
I originally had a problem with `uninitialized' warnings
when trying to reproduce your problem but it turned out to
be because I had
[ ... stuff ... ]
my @baz = map { ( $_ , shift @bar ) } @foo;
print STDOUT my @baz = map { ( $_ , shift @bar ) } @foo;
This, of course, eats up @bar the first time
so there's nothing left to shift the second
time. :(
What's on your lines 1 and 2?
As for the general problem of warnings, I only turn warnings off for short one-shot scripts that I know will work even though I wrote bad code. Or, rather, I ignore them unless they get in the way of the output.
I've never encountered a warning (from perl) that wasn't justified so if I'm doing anything at all important I eliminate them. | [reply] [d/l] [select] |
Re: interleave two arrays
by danger (Priest) on Feb 03, 2001 at 02:48 UTC
|
This can also be used to interleave arrays, though it is
more suited to iterating through them rather than just building the
interleaved list (also, take note of chipmunk's correction to
handle parallel undefs).
| [reply] |
Re: interleave two arrays
by dkubb (Deacon) on Feb 03, 2001 at 09:44 UTC
|
#!/usr/bin/perl -w
use strict;
my @keys = qw(a b c d);
my @values = qw(1 2 3 4);
print interleave(\@keys, \@values);
sub interleave {
my %interleaved;
@interleaved{ @{$_[0]} } = @{$_[1]};
return %interleaved;
}
| [reply] [d/l] |
|
| [reply] |
|
Thank you for pointing my mistake in using
a hash slice to interleave two lists, tye. Here's
my second attempt at interleaving two lists. This
time I use an array slice, and (hope this makes sense) calculates the offset position for the two arrays in the final interleaved array:
#!/usr/bin/perl -w
use strict;
use Data::Dumper qw(Dumper);
my @keys = qw(a b c d e f g h i j); #is longer than
my @values = qw(1 2 3 4 5); #this..
my @array = interleave(\@keys, \@values);
print Dumper(\@array); #let's see what happens
sub interleave {
my $array1 = shift;
my $array2 = shift;
my(@even, @odd);
push @even, $_ * 2 for 0..$#$array1;
push @odd, $_ * 2 + 1 for 0..$#$array2;
my @interleaved;
@interleaved[@even, @odd] = (@$array1, @$array2);
return wantarray ? @interleaved : \@interleaved;
}
__END__
If one of the arrays is longer than the other, it will
still interleave them as if they are the same length. This
behaviour is essential if the interleaved array ever gets
copied to a hash, or you need the array elements to be
in pairs.
The method that I used to calculate the offsets inside
interleave() is the fastest I could find through benchmarking. If
there is a faster/cleaner/better way, I would love to hear it. | [reply] [d/l] [select] |
Re: interleave two arrays
by mechagodzilla (Initiate) on Dec 21, 2010 at 08:18 UTC
|
my @outies = mesh (@lines1,@lines2, @lines3);
| [reply] [d/l] |
Re: interleave two arrays
by kloro2006 (Initiate) on Feb 02, 2014 at 23:07 UTC
|
#the following gives: a 1 b 2 c 3
@arr1 = qw(a b c);
@arr2 = qw(1 2 3);
while (@arr1) {push @arr3, shift @arr1,shift @arr2}
print "@arr3";
#BUT why does the following give an infinite loop?
@arr1 = qw(a b c);
@arr2 = qw(1 2 3);
while ($push @arr3, shift @arr1,shift @arr2){}
| [reply] [d/l] |
|
| [reply] |
|
thanks.
how do i edit an item i've already posted?
| [reply] |