Re: insert element into an array
by TedPride (Priest) on Nov 16, 2004 at 14:19 UTC
|
The problem is that you're splicing the main array, not the nested array, so everything after the found line gets pushed forward one, and the line gets found again endlessly. A better piece of code would be:
use strict;
use warnings;
my @R; # Constructing your matrix...
while (<DATA>) { chomp; push @R, [split(/ /)]; }
for (@R) {
if ($_->[0] eq 'a') {
unshift @$_, '#'; print join("\t", @$_)."\n";
}
}
__DATA__
x y z
a b c
e f g
h i j
EDIT: And here's your code, modified so it works. I'd personally use unshift rather than splice, though...
for my $rc(@R) {
if ($rc->[0] eq "a") {
splice @$rc, 0, 0, '#';
print "$rc->[0]\t","$rc->[1]\t","$rc->[2]\t","$rc->[3]
+\n";
}
}
You were missing a > and a ; on line 4, btw. | [reply] [d/l] [select] |
|
|
Thanks for your (and Dave's) answer.
You mention you'd rather use unshift, is this for any particular reason (like performance maybe) ?
As a newbie to Perl I'd like to understand which is the preferred method. Or is it just down to personal choice ?
In this particular case I wouldn't expect the matrix to be more than about 100 records by the way.
| [reply] |
|
|
Something leads me to believe performance is the same with both (but Benchmark if you want to be sure). The reason would be readability. splice(@a, 0, 0, $val); is not even closely as readable as unshift(@$rc, $val);.
By the way, Perl is very efficient at adding to and removing from both the front and the end of arrays. That includes shift, unshift, push, pop, their splice equivalents, and probably $a[@a] = $val.
| [reply] [d/l] [select] |
Re: insert element into an array
by davorg (Chancellor) on Nov 16, 2004 at 14:21 UTC
|
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my @R = ([qw(x y z)], [qw(a b c)], [qw(e f g)], [qw(h i j)]);
print Dumper \@R;
for my $rc (@R) {
if ($rc->[0] eq "a") {
splice @$rc, 0, 0, '#';
print "$rc->[0]\t","$rc->[1]\t","$rc->[2]\t","$rc->[3]\n"
}
}
print Dumper \@R;
splice @$rc instead of splice @R.
--
< http://www.dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] [d/l] |
|
|
I obviously have a lot to learn about about the wonders of splice with arrays.
If using your example I wanted to delete the row instead of insert a new element, how would I do it ?
I tried
for my $rc (@R) {
if ($rc->[0] eq "a") {
splice @$rc, 0, 2;
}
}
but this just removes everything (including the line I want to delete) up to the end of the array
I also tried this
for my $rc (@R) {
if ($rc->[0] eq "a") {
delete $rc->[0-2];
}
}
This works but then when I try to print the array out I get an uninitialized value in concatenation error.
I'd expected this because the array wasn't scrunched up and delete is not the right thing to use I guess.
The print I used was
foreach (@records) {
$buf .= "$_->[0] $_->[1] $_->[2] $_->[3]\n";
print $buf;
}
| [reply] [d/l] [select] |
|
|
Once again you're splicing the wrong array :) If you want to remove a row, then you want to alter the outer array, @R.
But in this case, splice is really the wrong tool. Here you probably want to use grep.
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my @R = ([qw(x y z)], [qw(a b c)], [qw(e f g)], [qw(h i j)]);
print Dumper \@R;
@R = grep { $_->[0] ne 'a' } @R;
print Dumper \@R;
--
< http://www.dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] [d/l] |
|
|
Re: insert element into an array
by ysth (Canon) on Nov 16, 2004 at 17:12 UTC
|
Several comments:
Don't modify the array that you are for()'ing over. (Modifying the elements is fine, but inserting or deleting can have interesting interaction.)
Your code inserts # at the beginning of the array, not just before the "a", but once you find an "a", you move the a forward so you will find it on the next iteration of the loop, and then you do it again, and again... Try: my @a = qw/x y z
a b c
e f g
h i j/;
my $skip;
for (@a) {
if ($_ eq "a" && ($skip = !$skip)) {
splice @a, 0, 0, "#";
}
}
If you really want the "#" just before the "a", something like this is a lot easier:
@a = map {$_ eq "a" ? ("#","a") : $_} @a;
| [reply] [d/l] [select] |
Re: insert element into an array
by rev_1318 (Chaplain) on Nov 16, 2004 at 14:12 UTC
|
please submit a small, but complete program that produces the output you show us. You speak of an array, but show us the diagram of a matrix.
Paul
| [reply] |
|
|
Apologies. here is the missing bit
Input file looks like (space delimited)
a b c
d e f
h i j
k l j
File reader code
my ($in,$KKK);
while( sysread(IN,$in,length(hello)) ) {
$KKK .= $in;
}
my @R = map{ [ split /\s+/ ] }split /\n/, $KKK;
Hope this helps
| [reply] [d/l] |