Re: Simple iteration problem
by moritz (Cardinal) on Nov 29, 2007 at 13:56 UTC
|
1) You don't check if open succeeds. That's bad.
2) If you want to substract, why do you use strings?
3) Assignment is =, not eq
| [reply] |
Re: Simple iteration problem
by Anonymous Monk on Nov 29, 2007 at 14:18 UTC
|
use warnings;
use strict;
open TAB, "test.txt";
You should always verify that the file opened correctly:
open TAB, '<', 'test.txt' or die "Cannot open 'test.txt' $!";
$diff = "$tab[0]" - "$seed";
You are converting the contents of the variables to strings and then subtracting which converts them back to numbers. Just use the variables directly:
$diff = $tab[0] - $seed;
if ($diff ge 0.1)
You are using a text comparison operator on numeric data when you should be using a numerical comparison operator:
if ($diff >= 0.1)
{print "@tab\n" && $seed eq $tab[0]}
The logical AND operator && has relatively low precedence so it is evaluated first and the result of "@tab\n" && $seed eq $tab[0] is passed to the print operator.
{print "@tab\n"; $seed eq $tab[0]}
| [reply] [d/l] [select] |
|
|
I agree with much of this. However, i think it should be:
$seed = $tab[0];
Etbr77, here is my version (which is nearly identical to AnonMonk's):
use warnings;
use strict;
open TAB, '<', 'test.txt' or die "Can not open file: $!";
my $seed = 1.04;
while (<TAB>) {
chomp;
my @tab = split / /;
my $diff = $tab[0] - $seed;
if ($diff >= 0.1) {
print "tab[0]=$tab[0]\n";
$seed = $tab[0];
}
}
close TAB;
Since I really have no idea what your input file looks like,
I created my own sample input file (test.txt):
3
5 6 7
2 22 222
10 9
When I run this script, I get the following output:
tab[0]=3
tab[0]=5
tab[0]=10
If this is not what you are looking for, please provide a small sample of your input, and expected output.
Update: Removed unnecessary else, thanks to Eimi Metamorphoumai. | [reply] [d/l] [select] |
|
|
I'd just like to add that there's really no reason to include the
else {
next;
};
part, since without it the functionality is exactly the same. | [reply] [d/l] |
|
|
It works great now!
Thank you all very much.
| [reply] |
|
|
I used your suggestions to create the following script, which is still not quite right. It spits out all of the values in tab[0], whether or not they meet the criterion of the difference in $seed minus $tab[0] being greater than 0.1
I removed the use warnings and strict, just for the moment.
#!/usr/bin/perl
open TAB, '<', 'test.txt' or die "Cannot open 'test.txt' $!";
<TAB>;
$seed = 1.04;
while (<TAB>){
@tab = split ' ';
$diff = $tab[0] - $seed;
if ($diff >= 0.1) {print "@tab\n"; $seed eq $tab[0]} else {next};
}
| [reply] [d/l] |
|
|
Gah!!
I removed the use warnings and strict, just for the moment.
Why, oh why would you do that?
<tongue_in_cheek>
Are you trying to make debugging more "interesting" by hiding clues from yourself?
If so, don't bother reading about "use diagnostics" which may make debugging even less interesting!
</tongue_in_cheek>
...roboticus
| [reply] |
|
|
| [reply] |
Re: Simple iteration problem
by cdarke (Prior) on Nov 29, 2007 at 14:03 UTC
|
eq is for comparing text, use == for numerics.
ge is for comparing text, use >= for numerics. | [reply] |
Re: Simple iteration problem
by goibhniu (Hermit) on Nov 29, 2007 at 16:40 UTC
|
++Moritz and Anonymonk and toolic for encouraging good programming. I learned the hard way to always use strict; use warnings;. This will help Perl help you catch your own errors.
update: toolic and Eimi Metamorphoumai have pointed out that much of my concern about @tab was for nought.
<blockignore quality="sheepish">
I think there's one more thing to comment on in your code. The value of @tab is the number of elements in the array. I personally think that toolic's output is more helpful and is certainly more instructive, but if you really wanted the number of elements in the array, you'd have gotten:
1
3
2
for toolic's results, since that's the number of elements in the arrays on the lines that satisfy the conditional.
If you wanted to print the array instead of either the first element of the array or the number of elements, print takes a list and you can cast @tab into a list as:
print (@tab,"\n");
When I did this it jammed the elements of the array all together as:
3
567
109
and I solved that with:
print join(' ',@tab,"\n");
</blockignore>
Finally, just for fun I turned it into a one-liner. This risks encouraging some bad programming (I didn't use strictures in my one liner), but it takes advantage of several things. perl -n replaces the outer while (<TAB>) loop. perl -a automatically spilts it for you into an array, @F. perl -l automatically handldes the newline when printing. This was on Win32, so your delimeters may vary (YDMV?).
C:\chas_sandbox>type test653837.txt
3
5 6 7
2 22 222
10 9
C:\chas_sandbox>perl -lane "$seed = 1.04 unless $seed;$diff=$F[0]-$see
+d;if ($dif
f>=0.1) {print join(' ',@F);$seed=$F[0];}" test653837.txt
3
5 6 7
10 9
| [reply] [d/l] [select] |
|
|
print join(' ',@tab,"\n");
There is no need to use join in this case. This will accomplish the same thing:
print "@tab\n";
When interpolating an array inside double-quotes, the value of the $" special variable is used to separate elements of the array. The default value of $" is a single space. See perlvar, and search for LIST_SEPARATOR. | [reply] [d/l] [select] |
|
|
Actually, @tab inside a string interpolates to the contents of the array, separated by $" (a single space by default). For instance,
my @tab = (3,7);
print "@tab\n";
will print "3 7". Try it yourself. | [reply] [d/l] [select] |