Test loop

K

KaZ

Hi,

I'm trying to do the following:
for each value of an array, make a test.
If the loop comes to the end without that the test became true a single
time, do action A. Otherwise, just go on, without doing action A.

Can somebody help me here? Thanks a lot!
 
G

Gunnar Hjalmarsson

KaZ said:
I'm trying to do the following:
for each value of an array, make a test.
If the loop comes to the end without that the test became true a single
time, do action A. Otherwise, just go on, without doing action A.

Use the grep() function in scalar context.

perldoc -f grep
 
J

Josef Moellers

KaZ said:
Hi,

I'm trying to do the following:
for each value of an array, make a test.
If the loop comes to the end without that the test became true a single
time, do action A. Otherwise, just go on, without doing action A.

Can somebody help me here? Thanks a lot!

What have you tried so far? Where has it failed to work as expected?

Have you looked at the "map" operator?

Josef
 
M

Mirco Wahab

Thus spoke KaZ (on 2006-06-26 10:45):
I'm trying to do the following:
for each value of an array, make a test.
If the loop comes to the end without that the test became true a single
time, do action A. Otherwise, just go on, without doing action A.

Can somebody help me here? Thanks a lot!

As Gunnar already said, use the 'grep' operator.

To be more specific: use something like

...
if( not grep { condition_of $_ } @array ) {
print "do something";
}
else {
print "go ahead";
}
...

grep pulls all elements from @array,
transfers them one-at-a-time into it's
block, accessible as $_ - and, depending
on the outcome of your 'condition',
and constructs another list corresponding
to the 'true' values only.

If there are no 'true' values, grep
returns an empty list, which gives
in the scalar context of the 'if'
a (length) value of 0/zero/false.

Regards

Mirco
 
K

KaZ

Mirco said:
As Gunnar already said, use the 'grep' operator.

To be more specific: use something like

...
if( not grep { condition_of $_ } @array ) {
print "do something";
}
else {
print "go ahead";
}
...

grep pulls all elements from @array,
transfers them one-at-a-time into it's
block, accessible as $_ - and, depending
on the outcome of your 'condition',
and constructs another list corresponding
to the 'true' values only.

If there are no 'true' values, grep
returns an empty list, which gives
in the scalar context of the 'if'
a (length) value of 0/zero/false.

Regards

Mirco

Thanks a lot!

To be more precise, I want to write a line in a file only if it hasn't
already been written in it. So I have to scan the lines of the file
with a foreach loop, and if the line wasn't found, I wrote it in.

I made it with loop-controlers until here, but it isn't very good
programming in my opinion.

So, actually, I have another question: is it possible to open the file
only once at the beginning of the script (I'm writing a script), search
it for a line, append lines, without having to close and reopen it?
Because opening and closing files a lot of times make the script quite
slow, as far as I can tell, and I want to process very big files with
it, so speed matters.

Greetings,
kaz
 
M

Mirco Wahab

Thus spoke KaZ (on 2006-06-26 11:55):
To be more precise, I want to write a line in a file only if it hasn't
already been written in it. So I have to scan the lines of the file
with a foreach loop, and if the line wasn't found, I wrote it in.

I made it with loop-controlers until here, but it isn't very good
programming in my opinion.

So, actually, I have another question: is it possible to open the file
only once at the beginning of the script (I'm writing a script), search
it for a line, append lines, without having to close and reopen it?
Because opening and closing files a lot of times make the script quite
slow, as far as I can tell, and I want to process very big files with
it, so speed matters.

Open the File:

open(my $fh , '<', $filename) or die "without hesitation $!";

Read the file into an array and close it

my @fa = <$fh>;
close $fh;

Do all comparisons on the array, never on the file

for( all_things_to_do ) {
work_on_array_only( @array );
}


If done, write the array back to the file,
(you may save a backup before if necessary)
replace it:

open($fh , '>', $filename) or die "WTF $!";
print $fh @array;
close $fh;


Above statements draw the outline only.
Now you have to make sense of it ;-)

Regards

Mirco
 
K

KaZ

Many thanks for your help!

I still have a strange problem: I use the grep to search the array like
this:
if (not grep { "blah:$var" } @foo) {...}

But I can put whatever I want instead of "blah:$var", like "kfdhkf",
really anything, the grep is going to match. Except when the array is
empty.

I made a print grep .... and it always returns the first element of the
array, whatever I ask the grep to search for.

I missed something, but I can't find out what. If you habe any idea
about this...
 
T

Tad McClellan

KaZ said:
So, actually, I have another question:


Then you should also have another Subject (ie. start a new thread).

People that know how to read and change files without reopening
will not look for questions they can answer hidden under a Subject
about looping.

Have you seen the Posting Guidelines that are posted here frequently?

is it possible to open the file
only once at the beginning of the script (I'm writing a script), search
it for a line, append lines, without having to close and reopen it?


perldoc -f seek

perldoc -q file

How do I change one line in a file/
delete a line in a file/
insert a line in the middle of a file/
append to the beginning of a file?
 
X

xhoster

KaZ said:
So, actually, I have another question: is it possible to open the file
only once at the beginning of the script (I'm writing a script), search
it for a line, append lines, without having to close and reopen it?
Because opening and closing files a lot of times make the script quite
slow, as far as I can tell, and I want to process very big files with
it, so speed matters.

It doesn't take any longer to open a large file than a small one. If the
file is very big, then reading the whole thing in order to do the search is
going to take far more time opening and closing it will. If you are
worried about time, then you need to come up with a better method that
searching through an entire file every time. Use a database or a (possibly
tied) hash. Having said that, you can use "seek" both to rewind a file
handle to the beginning, and to move the file handle to the end.

Xho
 
T

Ted Zlatanov

I'm trying to do the following:
for each value of an array, make a test.
If the loop comes to the end without that the test became true a single
time, do action A. Otherwise, just go on, without doing action A.

my $successful_test = 0;

foreach my $value (@values)
{
$successful_test ||= run_test($value);
}

runActionA() unless $successful_test;

Various grep/map solutions are possible but this is probably easiest
to understand.

Ted
 
T

Ted Zlatanov

To be more precise, I want to write a line in a file only if it hasn't
already been written in it. So I have to scan the lines of the file
with a foreach loop, and if the line wasn't found, I wrote it in.

# allow multiple lines to be inserted, and assume order doesn't matter
my %newlines = ( 'line 1' => 1, 'line 2' => 1);
open F, "<$file" or die "Couldn't open $file: $!";
while (<F>)
{
chomp;
delete $newlines{$_} if exists $newslines{$_};
}
close F;

open F, ">>$file" or die "Couldn't open $file for appending: $!";
print F "$_\n" foreach keys %newlines;
close F;
So, actually, I have another question: is it possible to open the file
only once at the beginning of the script (I'm writing a script), search
it for a line, append lines, without having to close and reopen it?
Because opening and closing files a lot of times make the script quite
slow, as far as I can tell, and I want to process very big files with
it, so speed matters.

Others have answered this. My advice is to keep it simple - instead
of opening read/write, try to open read-only and then write when you
have the data ready. Of course this is not always true, sometimes you
really need read/write opens and complicated algorithms, but you
should always look for the simple solution first. This is not so much
Occam's razor as common sense: simple solutions are easier to program,
test, and debug.

Ted
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,197
Messages
2,571,040
Members
47,634
Latest member
RonnyBoelk

Latest Threads

Top