# Switching the contents of two arrays. - Page 3

•  Subject
• Author
• Posted on

## Re: Switching the contents of two arrays.

I didn't write that.

## Re: Switching the contents of two arrays.

I didn't write that. I gave a detailed explanation why I consider the

@B = reverse map {  pop @A  }  1 .. unshift(@A, @B) -  @B;

at best a not terribly witty prank and at worst, totally boring copycat
stuff. And posting a further 50 trivial rehashes of that, such as

is not going to convey a different expression to me. It's all just "put
all values onto one array, extract some of them back out again".

## Re: Switching the contents of two arrays.

[...]

"Obscure, dark corners" most likely just contain old rubbish.

Another simple idea: Swap every element of the common head of both
arrays, then, move the tail of the longer one to the shorter.

---------
my @a = qw(a b c d e f g);
my @b = (1, 2, 3);

sub swap
{
@_[0, 1] = @_[1, 0];
}

sub aswap_again(\@\@)
{
my (\$a0, \$a1) = @_;

swap(\$a0, \$a1) if @\$a1 < @\$a0;
swap(\$a0->[\$_], \$a1->[\$_]) for 0 .. \$#\$a0;
push(@\$a0, splice(@\$a1, @\$a0));
}

aswap_again(@a, @b);

print(join(',', @a), "\n");
print(join(',', @b), "\n");
----------

## Re: Switching the contents of two arrays.

One simple way is to use array references:

my @array_ref1 = [ qw(1 2 3 4 5 6 7) ];
my @array_ref2 = [ qw(10 11 12 13 14 15) ];

( \$array_ref1, \$array_ref2 ) = ( \$array_ref2, \$array_ref1 );

Using references does complicate accessing the array elements somewhat,
but that can be more efficient in some cases, as you can avoid making
copies of the array. For example, if you pass an array reference to a
subroutine, you avoid copying the entire array into the @_ array. You
can also intersperse arrays and scalars in the argument list more
freely.

--
Jim Gibson

## Re: Switching the contents of two arrays.

This creates two lexically scoped arrays each containing a reference to
an anonymous array as sole element, followed by swapping the values of
two package-variables with similar names.

----------
my @array_ref1 = [ qw(1 2 3 4 5 6 7) ];
my @array_ref2 = [ qw(10 11 12 13 14 15) ];

print "@array_ref1\n";
print "@array_ref2\n";

( \$array_ref1, \$array_ref2 ) = ( \$array_ref2, \$array_ref1 );

print "@array_ref1\n";
print "@array_ref2\n";
----------

It should have created two lexically scoped scalars instead,

----------
my \$array_ref1 = [ qw(1 2 3 4 5 6 7) ];
my \$array_ref2 = [ qw(10 11 12 13 14 15) ];

print "@\$array_ref1\n";
print "@\$array_ref2\n";

( \$array_ref1, \$array_ref2 ) = ( \$array_ref2, \$array_ref1 );

print "@\$array_ref1\n";
print "@\$array_ref2\n";
---------

## Re: Switching the contents of two arrays.

Thanks for correcting that.

--
Jim Gibson

## Re: Switching the contents of two arrays.

On 11/28/2015 6:06 AM, Jim Gibson wrote:

I had considered just using array references, and had the same thoughts

Somewhere I thought I had run into this problem before and had come up
with a rather elegant solution, but I can't remember what the solution
was or what code had that solution. Or whether I actually did have a
more elegant solution. I thought that if there was a more elegant
solution, better minds than mine would know what it is.

Speed isn't a big concern, and neither array will ever have more than
three elements in it, so the clarity of using a temporary named array
may win out over other solutions.

## Re: Switching the contents of two arrays.

[...]

... and this is a lot closer to how other languages handle arrays, in
particular, Java, where arrays are treated like objects in this respect,
ie, an array variable is always a reference to an array, or C, where
attempts to access 'arrays' end up working with a pointer to the first
element (and every valid pointer actually points to an array of a
certain length, even if the length is just 1).

I used to write Perl like this for a long time (more than 15 years)
because it was closer to 'my idea of the things' (not influenced by Java
which I only learnt about 3 years ago) but in the context of a somewhat
larger program (ca 18,000 LOC right now and steadily growing), this
ended up very messy: Functions would take arguments lists, some of
the arguments being references to arrays, and return result list, some of
the again being references to arrays, with no clear reason why certain
arguments where passed or return within [] and others were not. Often,
functions would need to make copies of anonymous array references passed
to them (some times multiple levels deep inside the callstack) to avoid
changing the value of the caller. Sometimes, they were supposed to
change this value. There were a lot of "individual" and rather intricate
local conventions and this led to frequent 'surprises', eg, when calling
a function with believed-to-be-known behaviour which called a function
calling a function changing a [] passed to it because this made sense in
the original context but it didn't make sense in the new context
anymore.

Since I didn't feel like "in order to cope with the mess,
mess-management has to be formalized", I've instead settled on

- don't use anonymous arrays unless there's an specific reason
why a named array or a list of argument or a list of return
values can't do the job

- in particular, don't use anonymous arrays for "proactive
performance optimization" (instead of named arrays)

- in case an anonymous array is used to group a set of related
values together, turn it into a class/ an object unless
relevant, adverse performance effects demonstrably exist

[- unless there's a specific reason to do otherwise, don't use
hashes for object representation as there's no 'natural' way
to extend a hash]

So far, I'm rather happy with this.

## Re: Switching the contents of two arrays.

rweikusat@talktalk.net says...

Ranier, what does this mean?  Thanks.

John Black

## Re: Switching the contents of two arrays.

what do you mean with that ?
Blessing an array instead of a hash ?
And what is the "there's no 'natural' way to extend a hash" ?!!!!

I have some very big OO projects working perfect that would take x10
times to code em with java or c

## Re: Switching the contents of two arrays.

What I wrote: A record is an ordered sequence of named fields. A hash is
an unordered mapping of keys (arbitrary sequences of bytes) to values. A
hash is similar to a record insofar it can map arbitrary keys to 'some
storage location', however, it's unstructured: All users of a certain
hash share a 'flat' keyspace and thus, need to agree on some scheme for
'key de-ambiguitation', eg, the usual C convention of prefixing the
module name (however defined) to the real key

An array is similar to a record insofar it provides an ordered set of
locations, but 'names' are restricted to indices. But this has also some
advantages, in particular, allocating some set of so-far unused array
locations to a new user is easy: Keep track of the highest used
index. For n locations, use (index + 1, index + n), set index to index +
n afterwards. The array can be 'extended at the end' without affecting
existing users. This makes it a good candidate for representing objects
in a single-inheritance hierarchy. The problem of "user-unfriendly slot
names" can be solved by defining suitable (Perl) constants via
constant.pm. There's no problem with 'global name clashes' here because
the corresponding names belong to the defining package. As an added
bonus, the compiler can (when using strict) check named field accesses
without having to resort to run-time hacks a la "undefined value
converted to something!".

It's even fairly easy to manage hierachically assigned slots in this way
by hand but considering that 'the next n free slots' can be determined
algorithmically, this can also be offloaded to the computer. Like this,
for instance:

----------
package slots;

use Carp;
use constant;

my %counters;

sub import
{
my (\$ctr, \$fields);

shift;
return unless @_;

if (ref(\$_[0])) {
\$ctr = 0;
} else {
exists(\$counters) or croak("unknown parent \$_[0]");
\$ctr = \$counters;

shift;
}

\$fields = \$_[0];
@_ = ('constant', {map { \$_, \$ctr++; } @\$fields});

\$counters = \$ctr;

goto &constant::import if @\$fields;
}

1;
---------

This used to be accessible on a web server but since that is rather
ancient, I'm no so keen on keeping it running and my desire for
"fortuneless fame" is far too low to even consider dealing with the CPAN
bureaucracy.

... until the next runtime error on some rarely use codepath ...

But I didn't write that the code didn't work, just that the effort
'inspirational' abuse of that) was larger than the benefit from "using
anonymous arrays" turned out to be.

Documentation for the above:

# This is intended to be a minimal addition to the built-in
# Perl 5 OO support facilities which turn these into a
# 'full-featured' OO system supporting both method and
# data inheritance. It provides 'hierarchical slot allocation'
# enabling a reference to an anonymous array to be used as
# object representation for a set of cooperating packages.
#
# There are three (sensible) ways to use it:
#
# 1. In a 'root class' (ie, one which is not derived from
# any other class):
#
# use slots [qw(A B C D)];
#
# This will create Perl constants (via constant.pm) named
# A, B, C and D which can be used to access four distinct
# slots of an array for storing 'object properties'.
#
# 2. In a derived class
#
# use slots ('Parent', [qw(A B)]);
#
# This will create two Perl constants named A and B which can
# be used to access two distinct array slots which haven't
# already been allocated to Parent or any of its 'data
# inheritance superclasses'.
#
# 3. In an 'intermediate' class which doesn't require any
# properties itself:
#
# use slots 'Parent';
#
# This enables classes derived from the intermediate class
# to base their properties on that instead of on the next
# superclass which actually defines any properties.
#
# NB: This slot allocation scheme (and the idea to use
# arrays as an object representation in general) is limited
# to single-inheritance data hierarchies. I haven't found
# this to be a critical limitation in practice.
#
#
# This module is free software; you can redistribute it or modify it
# under the same terms as Perl itself.

## Re: Switching the contents of two arrays.

On 27/11/2015 22:06, Scott Bryce wrote:

your request is usefull for some perl fun time.
if really have to do some serious job I would the following and nothing else

#!/usr/bin/perl
use strict; use warnings;

my %RowData=(
uuid1=> [qw/a b c/],
uuid2=> [qw/A B C D E/],
uuid3=> [qw/1 2 3/],
);

my \$array1 = \$RowData;
my \$array2 = \$RowData;
my \$array2 = \$RowData;
my \$array2 = \$RowData;

## Re: Switching the contents of two arrays.

On 27.11.15 21:06, Scott Bryce wrote:

For numbers in them, you could use `^':

my @array_1 = (1, 2, 3, 4, 5, 6, 7);
my @array_2 = (10, 11, 12, 13, 14, 15);

\$k = 0;
for (@array_1) {
\$array_2[\$k] = \$_ ^ \$array_2[\$k],
\$_           = \$_ ^ \$array_2[\$k],
\$array_2[\$k] = \$_ ^ \$array_2[\$k];

++\$k;
}

## Re: Switching the contents of two arrays.

On 2/12/2015 15:46, G.B. wrote:

very nice

## Re: Switching the contents of two arrays.

That's a pretty old trick and it was the well-known downside that the
two 'things' to swap must be different, otherwise, it'll ends up
producing zeroes:

---------
sub aswap(\@\@)
{
my (\$a0, \$a1) = @_;
my \$n;

for (@\$a0) {
\$a1->[\$n] ^= \$_;
\$_ ^= \$a1->[\$n];
\$a1->[\$n] ^= \$_;

++\$n;
}
}

my @a = (1, 2, 3);
my @b = (4, 5, 6);

aswap(@a, @b);

print("@a\n");
print("@b\n");

aswap(@a, @a);

print("@a\n");
--------