Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Problem with splice in a 2D ARRAY

29 views
Skip to first unread message

gamo

unread,
Jun 17, 2013, 7:04:24 AM6/17/13
to

Hello, I have a 2D array and want to interchange rows and columns.

I have done this test and it fails talking about flips and flops.
The perldoc -f splice is not of much help to swap 2 rows in a 2D
array (4 parameters as argument).

#!/usr/local/bin/perl -W

for $x (0,1){
for $y (0,1){
$xy[$x][$y]= ++$count;
}
}

splice @xy, 0, 1, $xy[1][0..1];



for $x (0,1){
for $y (0,1){
print "$xy[$x][$y] ";
}
print "\n";
}

__END__

Thanks in advance for any help


Rainer Weikusat

unread,
Jun 17, 2013, 7:56:41 AM6/17/13
to
gamo <ga...@telecable.es> writes:
> Hello, I have a 2D array and want to interchange rows and columns.
>
> I have done this test and it fails talking about flips and flops.
> The perldoc -f splice is not of much help to swap 2 rows in a 2D
> array (4 parameters as argument).
>
> #!/usr/local/bin/perl -W
>
> for $x (0,1){
> for $y (0,1){
> $xy[$x][$y]= ++$count;
> }
> }

There is no such thing as 'a 2D array' in Perl. What you create here
is a two-element array containing two references to two anonymous
two-element arrays each containing two numbers each. Swapping the two
'rows' aka 'anonymous two-element arrays' can be done with

@xy[0,1] = @xy[1,0]

or

splice(@xy, 0, 2, @xy[1,0])

Rainer Weikusat

unread,
Jun 17, 2013, 7:57:17 AM6/17/13
to
gamo <ga...@telecable.es> writes:
> Hello, I have a 2D array and want to interchange rows and columns.
>
> I have done this test and it fails talking about flips and flops.
> The perldoc -f splice is not of much help to swap 2 rows in a 2D
> array (4 parameters as argument).
>
> #!/usr/local/bin/perl -W
>
> for $x (0,1){
> for $y (0,1){
> $xy[$x][$y]= ++$count;
> }
> }

There is no such thing as 'a 2D array' in Perl. What you create here
is a two-element array containing two references to two anonymous
two-element arrays each containing two numbers. Swapping the two

gamo

unread,
Jun 17, 2013, 8:43:23 AM6/17/13
to
Rainer Weikusat <rwei...@mssgmbh.com> Wrote in message:
Both works fine, but as I infer there is no simple way to do that
by columns.

thank you very much

--
posted by mobile device



----Android NewsGroup Reader----
http://www.piaohong.tk/newsgroup

Ben Morrow

unread,
Jun 17, 2013, 11:02:27 AM6/17/13
to

Quoth gamo <ga...@telecable.es>:
>
> Hello, I have a 2D array and want to interchange rows and columns.

Well, did you try the obvious way?

my @old = ...;
my @new;

for my $r (0..$#old) {
my $row = $old[$r];
for my $c (0..$#$row) {
$new[$c][$r] = $$row[$c];
}
}

I'm not sure it's possible to do that any more elegantly, given that you
can't take a slice vertically through a 2d array.

> I have done this test and it fails talking about flips and flops.
> The perldoc -f splice is not of much help to swap 2 rows in a 2D
> array (4 parameters as argument).
>
> #!/usr/local/bin/perl -W
>
> for $x (0,1){
> for $y (0,1){
> $xy[$x][$y]= ++$count;
> }
> }
>
> splice @xy, 0, 1, $xy[1][0..1];

What did you expect this to do? The 0..1 is in scalar context, so this
is the flip-flop operator, which I don't think is what you meant.

Ben

gamo

unread,
Jun 17, 2013, 12:31:27 PM6/17/13
to
for my $r (0..$#old) {
my $row = $old[$r];
for my $c (0..$#$row) {
$new[$c][$r] = $$row[$c];
}
}

I'm not sure it's possible to do that any more elegantly, given that you
can't take a slice vertically through a 2d array.

--------------------


Well, that does a tansposition, and after that is posible to do the
column swap:

my @xy = @new;

for $y (0,1){
($xy[0][$y],$xy[1][$y]) = ($xy[1][$y],$xy[0][$y]);
}

and redo the transposition. Or directly,

for $x (0,1){
($xy[$x][0],$xy[$x][1]) = ($xy[$x][1],$xy[$x][0]);
}

Anyway, it could be done without splice. Thank you, I'll try to resume
it to work with randomized small square matrix.

Best regards,


Rainer Weikusat

unread,
Jun 17, 2013, 12:57:41 PM6/17/13
to
Ben Morrow <b...@morrow.me.uk> writes:
> Quoth gamo <ga...@telecable.es>:
>>
>> Hello, I have a 2D array and want to interchange rows and columns.
>
> Well, did you try the obvious way?
>
> my @old = ...;
> my @new;
>
> for my $r (0..$#old) {
> my $row = $old[$r];
> for my $c (0..$#$row) {
> $new[$c][$r] = $$row[$c];
> }
> }
>
> I'm not sure it's possible to do that any more elegantly, given that you
> can't take a slice vertically through a 2d array.

sub transpose
{
my $in = $_[0];
my (@out, $col);

for $col (0 .. $#{$in->[0]}) {
push(@out, [map { $_->[$col] } @$in[0 .. $#$in]])
}

return \@out;
}

my @a = ([1,2,3,4], [4,5,6,7], [7,8,9,10]);
my $at = transpose(\@a);

for (@$at) {
print("$_ ") for @$_;
print("\n");
}

Rainer Weikusat

unread,
Jun 17, 2013, 1:11:32 PM6/17/13
to
Rainer Weikusat <rwei...@mssgmbh.com> writes:

[...]

> push(@out, [map { $_->[$col] } @$in[0 .. $#$in]])

This is, of course, equivalent to

push(@out, [map { $_->[$col] } @$in])

Ben Morrow

unread,
Jun 17, 2013, 2:58:23 PM6/17/13
to
Please quote properly, and attribute your quotations.

Quoth gamo <ga...@telecable.es>:
> [I wrote:]
>> for my $r (0..$#old) {
>> my $row = $old[$r];
>> for my $c (0..$#$row) {
>> $new[$c][$r] = $$row[$c];
>> }
>> }
>>
>> I'm not sure it's possible to do that any more elegantly, given that you
>> can't take a slice vertically through a 2d array.
>
> Well, that does a tansposition,

Yes. You asked how to interchange rows and columns; that's what a
transposition does.

> and after that is posible to do the
> column swap:
>
> my @xy = @new;
>
> for $y (0,1){
> ($xy[0][$y],$xy[1][$y]) = ($xy[1][$y],$xy[0][$y]);
> }
>
> and redo the transposition. Or directly,
>
> for $x (0,1){
> ($xy[$x][0],$xy[$x][1]) = ($xy[$x][1],$xy[$x][0]);
> }

So you're actually trying to exchange two columns. Yes, that is the way
to do it. For the more general case of reversing the columns of a NxM
matrix, you want

for my $r (@matrix) {
splice @$r, 0, $#r, reverse @$r;
}

You should look on CPAN: a lot of this sort of basic stuff has already
been implemented.

Ben

Ben Morrow

unread,
Jun 17, 2013, 2:50:50 PM6/17/13
to

Quoth Rainer Weikusat <rwei...@mssgmbh.com>:
> Ben Morrow <b...@morrow.me.uk> writes:
> > Quoth gamo <ga...@telecable.es>:
> >>
> >> Hello, I have a 2D array and want to interchange rows and columns.
> >
> > Well, did you try the obvious way?
> >
> > my @old = ...;
> > my @new;
> >
> > for my $r (0..$#old) {
> > my $row = $old[$r];
> > for my $c (0..$#$row) {
> > $new[$c][$r] = $$row[$c];
> > }
> > }
> >
> > I'm not sure it's possible to do that any more elegantly, given that you
> > can't take a slice vertically through a 2d array.
>
> sub transpose
> {
> my $in = $_[0];
> my (@out, $col);
>
> for $col (0 .. $#{$in->[0]}) {
> push(@out, [map { $_->[$col] } @$in[0 .. $#$in]])
> }

Yes, that's the same algorithm, just with map instead of for, though it
probably is worth pointing out that

map $_->[$col], @2d;

is the way to take a vertical slice.

Ben

ga...@telecable.es

unread,
Jun 17, 2013, 4:36:22 PM6/17/13
to
So you're actually trying to exchange two columns. Yes, that is the way
to do it. For the more general case of reversing the columns of a NxM
matrix, you want

for my $r (@matrix) {
splice @$r, 0, $#r, reverse @$r;
}

You should look on CPAN: a lot of this sort of basic stuff has already
been implemented.

Ben
---------------------------

very useful, thanks

I see things like Array::Utils, but it's about operations onm two matrix.
Math::MatrixReal is excelent but it's for computations purpose. I don't
know how to search more.

Thanks again


Rainer Weikusat

unread,
Jun 17, 2013, 4:57:26 PM6/17/13
to
Ben Morrow <b...@morrow.me.uk> writes:
> Quoth Rainer Weikusat <rwei...@mssgmbh.com>:
>> Ben Morrow <b...@morrow.me.uk> writes:
>> > Quoth gamo <ga...@telecable.es>:
>> >>
>> >> Hello, I have a 2D array and want to interchange rows and columns.
>> >
>> > Well, did you try the obvious way?
>> >
>> > my @old = ...;
>> > my @new;
>> >
>> > for my $r (0..$#old) {
>> > my $row = $old[$r];
>> > for my $c (0..$#$row) {
>> > $new[$c][$r] = $$row[$c];
>> > }
>> > }
>> >
>> > I'm not sure it's possible to do that any more elegantly, given that you
>> > can't take a slice vertically through a 2d array.
>>
>> sub transpose
>> {
>> my $in = $_[0];
>> my (@out, $col);
>>
>> for $col (0 .. $#{$in->[0]}) {
>> push(@out, [map { $_->[$col] } @$in[0 .. $#$in]])
>> }
>
> Yes, that's the same algorithm, just with map instead of for,

This means it is an equivalent algorithm and specifically,

> though it probably is worth pointing out that
>
> map $_->[$col], @2d;
>
> is the way to take a vertical slice.

I wrote it because it came to me that it was actually possible to get
'a vertical slice' out of 'a 2d array' with an expression instead of a
1-by-1 copying loop. It is also possible to get rid of the outer loop
(working with 'arrays' / 'lists' this time for a change):

sub transpose
{
my $col;

return map {
$col = $_;
[map { $_->[$col] } @_]
} 0 .. $#{$_[0]};
}

Charles DeRykus

unread,
Jun 17, 2013, 6:05:02 PM6/17/13
to
On 6/17/2013 1:36 PM, ga...@telecable.es wrote:
> for my $r (@matrix) {
> splice @$r, 0, $#r, reverse @$r;
> }


use List::MoreUtils qw/each_arrayref/;

my @old = (...);
my @new;

my $iter = each_arrayref( @old );
while (my @row = $iter->()) { push @new, [reverse @row] };

--
Charles DeRykus

Ben Morrow

unread,
Jun 17, 2013, 6:29:27 PM6/17/13
to
Quoth ga...@telecable.es:

Did you read the bit before where I asked you to quote properly? That
means: insert a '>' at the start of each line you are quoting, and
include a header saying whose message you are quoting from.

> [I wrote:]
>> So you're actually trying to exchange two columns. Yes, that is the way
>> to do it. For the more general case of reversing the columns of a NxM
>> matrix, you want
>>
>> for my $r (@matrix) {
>> splice @$r, 0, $#r, reverse @$r;
>> }
>>
>> You should look on CPAN: a lot of this sort of basic stuff has already
>> been implemented.
>
> very useful, thanks
>
> I see things like Array::Utils, but it's about operations onm two matrix.
> Math::MatrixReal is excelent but it's for computations purpose. I don't
> know how to search more.

Well, a quick look finds Math::Matrix and Array::DeepUtils, as well as
things like PDL which are probably a more suitable representation if
you're using matrices for calculations.

Ben

Charles DeRykus

unread,
Jun 18, 2013, 1:13:43 AM6/18/13
to
Sorry, I see the mis-attribution now... still not sure what was wanted.
But my above suggestion both transposes and swaps.

If just transposing with no swap:

my $iter = each_arrayref( @old );
while (my @row = $iter->()) { push @new, \@row };

--
Charles DeRykus







0 new messages