CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
Search Posts SEARCH
Who's Online WHO'S
Log in LOG

Home: Perl Programming Help: Intermediate:
splicing problem



Jan 4, 2001, 3:19 PM

Post #1 of 3 (301 views)
splicing problem Can't Post

i have a flat database which looks something like this:
21432|some text
23453|some text
35234|some text
93845|some text
(id number)|(message)
and so on

my problem is that i use checkboxes to select id numbers (several at a time). If a checked id number is present, that id number will be deleted from the record along with its message.
Here's the coding i use:

foreach $data (@data) { 
($id,$message) = split(/\|/, $data);
if ($FORM{$id} eq 1) {
splice(@data, $data_count, 1);

open (DATABASE, ">$dir") or &message("file error");
flock (DATABASE, 2);
print DATABASE @data;
flock (DATABASE, 8);

what ends up happening when i select multiple checkboxes is that the wrong database records get deleted. What i wanna know is if i can splice several records at a time, after pushing array numbers to a new array. I don't think that made sense, but hope someone can help =). Or if anyone has a completely different approach, i'm open to ideas.

User / Moderator

Jan 4, 2001, 6:13 PM

Post #2 of 3 (296 views)
Re: splicing problem [In reply to] Can't Post

Here is a solution that works. I assume that the datafile is not so huge that slurping the whole thing in is too expensive and that we will read and write to the same file.

#contents of my test 'inputdata' file
21432|some text a
23453|some text b
35234|some text c
93845|some text d

#variables that need setting (with my test data)
my %FORM = map { $_ => 1 } qw (21432 35234);
my $dir = 'inputdata';


open (LOCK, ">$dir.lck") or &message("semaphore error, could not open");
flock (LOCK, 2) or &message("semaphore error, could not flock");

open (DATABASE, $dir) or &message("file error, read $!");
my @data = <DATABASE>;
close (DATABASE);

@data = map { (exists $FORM{(split(/\|/, $_))[0]}) ? () : $_ } @data;

open (DATABASE, ">$dir") or &message("file error, write $!");
print DATABASE @data;
close (DATABASE);

close (LOCK);


Because we want to read and write the same file we need to flock a different file (a semaphore file) that can remain locked after we finish reading and get reset for writing. Also closing a flocked file will release the lock so there is no reason to explicitly release the flock.

But the real answer is all on this line...

@data = map { (exists $FORM{(split(/\|/, $_))[0]}) ? () : $_ } @data;

Starting with @data we do a split and see if the id from the first position exists in the %FORM hash. If it exists, then don't pass anything through " ? () ", otherwise send the whole line through " : $_ ". The new @data now is missing any lines that have id's that exist in %FORM.

The last time I gave an answer using this basic pattern...

map { (some test) ? $_ : () }

japhy pointed out that it was exactly what grep does. I think this one is better off with a map, but I could be wrong. Finding a grep solution for this line is left as an exercise for the reader.


Jan 5, 2001, 7:55 AM

Post #3 of 3 (289 views)
Re: splicing problem [In reply to] Can't Post

It is very dangerous to remove elements from an array while you are iterating over it. If you do this, you must do it safely and correctly. After investigation, I have come across a solution (although I'd really use rGeoffrey's method).

@a = (1..9); 
for (@a) {
if ($_ % 3 == 0) {
splice @a, --$x, 1;
print "@a\n";

This code produces the undesired results of:

1 2 4 5 6 7 8 9
1 2 4 6 7 8 9
1 2 4 6 8 9

As you can see, the first record is deleted fine, the second record is deleted ONE too early, and the third record is deleted TWO too early. This number is the number of records already deleted. To accomodate for this, I will store the size of the array in a variable, and then calculate the difference each time I splice():

$s = @a = (1..9); 
for (@a) {
if ($_ % 3 == 0) {
splice @a, --$x + ($s - @a), 1;
print "@a\n";

This gives me the expected output of:

1 2 4 5 6 7 8 9
1 2 4 5 7 8 9
1 2 4 5 7 8

Jeff "japhy" Pinyan -- accomplished hacker, teacher, lecturer, and author


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives