Ryuchi has asked for the wisdom of the Perl Monks concerning the following question:
I have a problem. I believe I have an array, @bigarray, like this:
[
['123*jeff','tortoise','qwerty']
['456*john','parrot','azerty']
['789*jane','budgie','abcdef']
]
I want to iterate over this to convert each row to:
['123','jeff','tortoise','qwerty']
Since I don't know how much additional data there is at the end*, I want to shift the data off, then unshift it back on.
However, I am having great difficulty with shift; it doesn't seem to want to work.
The splitting of the string is trivial; it's the shift/unshift which is being sticky.
my @row = $bigarray[$count];
print "dumper1:".Dumper(@row);
my $item = shift @row;
print "dumper2:".Dumper($item);
returns:
dumper1:$VAR1 = [
'<a href="http://www.wizards.com/default.asp?x=dnd/comp/mess
+age" title="Click to Subscribe" >Berronar\'s Salve</a>',
'Heroic',
'<em>Forgotten Realms Player\'s Guide</em>'
];
dumper2:$VAR1 = [
'<a href="http://www.wizards.com/default.asp?x=dnd/comp/mess
+age" title="Click to Subscribe" >Berronar\'s Salve</a>',
'Heroic',
'<em>Forgotten Realms Player\'s Guide</em>'
];
* Actually, I do, it varies.
Re: Shifting of 2D array slices
by jwkrahn (Abbot) on Dec 06, 2008 at 23:27 UTC
|
$ perl -le'
use Data::Dumper;
my @bigarray = (
[ "123*jeff", "tortoise", "qwerty" ],
[ "456*john", "parrot", "azerty" ],
[ "789*jane", "budgie", "abcdef" ],
);
print Dumper \@bigarray;
@bigarray = map [ map split( /\*/ ), @$_ ], @bigarray;
print Dumper \@bigarray;
'
$VAR1 = [
[
'123*jeff',
'tortoise',
'qwerty'
],
[
'456*john',
'parrot',
'azerty'
],
[
'789*jane',
'budgie',
'abcdef'
]
];
$VAR1 = [
[
'123',
'jeff',
'tortoise',
'qwerty'
],
[
'456',
'john',
'parrot',
'azerty'
],
[
'789',
'jane',
'budgie',
'abcdef'
]
];
| [reply] [d/l] |
|
@bigarray = map [ map split( /\*/ ), @$_ ], @bigarray;
The second map is not neccessary. The return value of map can be a list, so
@bigarray = map [ split /\*/ ], @bigarray;
will do fine, too.
| [reply] [d/l] [select] |
|
split, by default, operates on $_, but the elements of @bigarray are references. You need to explicitly dereference them and then split the elements. That's why the internal map is necessary. Your suggestion leaves @bigarray looking this way:
$VAR1 = [
[
'ARRAY(0x504290)'
],
[
'ARRAY(0x531f00)'
],
[
'ARRAY(0x531e60)'
]
];
| [reply] [d/l] [select] |
|
>perl -wMstrict -le
"use Data::Dumper;
my @bigarray = (
[ '123*jeff', 'tortoise', 'qwe*rty', ],
[ '456*john', 'parrot', 'aze*rty', ],
[ '789*jane', 'budgie', 'abc*def', ],
);
@bigarray =
map [ map split(/\*/), @$_ ],
@bigarray
;
print Dumper \@bigarray;
"
$VAR1 = [
[
'123',
'jeff',
'tortoise',
'qwe',
'rty'
],
[
'456',
'john',
'parrot',
'aze',
'rty'
],
[
'789',
'jane',
'budgie',
'abc',
'def'
]
];
>perl -wMstrict -le
"use Data::Dumper;
my @bigarray = (
[ '123*jeff', 'tortoise', 'qwe*rty', ],
[ '456*john', 'parrot', 'aze*rty', ],
[ '789*jane', 'budgie', 'abc*def', ],
);
@bigarray =
map [ split(/\*/, $_->[0]), @$_[ 1 .. $#$_ ] ],
@bigarray
;
print Dumper \@bigarray;
"
$VAR1 = [
[
'123',
'jeff',
'tortoise',
'qwe*rty'
],
[
'456',
'john',
'parrot',
'aze*rty'
],
[
'789',
'jane',
'budgie',
'abc*def'
]
];
Actually, I would prefer an approach using a for loop such as that of davidrw. In particular, the approach using splice can easily be modified to split any arbitrary element; this can also be done with the map approach, but with less concision. | [reply] [d/l] [select] |
Re: Shifting of 2D array slices
by moritz (Cardinal) on Dec 06, 2008 at 23:22 UTC
|
You seem to confuse arrays with references to arrays (short arrayrefs). Reading perlreftut, perllol (lists of lists) and perldsc should clear up things.
For example:
my @row = $bigarray[$count];
doesn't do what you want. Since $bigarry[$count] returns an arrayref, @row will contain only one value (that is, the reference). You'll probably want this instead:
my @row = @{$bigarray[$count]};
| [reply] [d/l] [select] |
Re: Shifting of 2D array slices
by davidrw (Prior) on Dec 07, 2008 at 01:22 UTC
|
Besides the map solutions already posted, here's two others:
setup for both:
use Data::Dumper;
my @bigarray = (
[ "123*jeff", "tortoise", "qwerty" ],
[ "456*john", "parrot", "azerty" ],
[ "789*jane", "budgie", "abcdef" ],
);
print Dumper \@bigarray; # before
...
print Dumper \@bigarray; # after
- Using splice:
splice @$_, 0, 1, split /\*/, $_->[0] for @bigarray;
- Using shift and unshift:
foreach my $arr ( @bigarray ){
my $item = shift @$arr;
unshift @$arr, split /\*/, $item;
}
| [reply] [d/l] [select] |
|
|