ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
aaah!! ic....
*noticing index range inside square bracket at the for statement*
okay,tnx so much but what I mean is like accessing from
array not just printing... Hmm how to say it...
well, here's another example.
Using c-style for loop
Code:
#!/usr/bin/perl
#printing only even number from an array
my @testAr=(6 .. 40);
for (my $i=0; $i<=$#testAr;$i++ )
{
if($testAr[$i]%2 == 0) {
print "$testAr[$i]\n";
}
}
Is the code above can be construct with perl's simple for loop ?
if it's not possible it's okay by me. Just want to see how much further perl can stay away from c...
I ask this because I'm trying to embrace more perlish style of perl code ... instead of C-ish perl code .Btw,my first prog lang is c so it's kinda hard for me to eliminate some c habit.
#!/usr/bin/perl
#printing only even number from an array
my @testAr=(6 .. 40);
for (my $i=0; $i<=$#testAr;$i++ )
{
if($testAr[$i]%2 == 0) {
print "$testAr[$i]\n";
}
}
Enter grep!
Code:
my @testAr=(6..40);
my @even = grep {$_ % 2 == 0} @testAr;
print "$_\n" for @even;
### OR ###
my @testAr=(6..40);
print "$_\n" for grep {$_ % 2 == 0} @testAr;
Put it this way, if you've specified an array, you can then access any element by num eg $arr[$n], without a loop, but you
need to be sure the array has a value at that index, or use the 'defined()' fn http://perldoc.perl.org/functions/defined.html.
HTH
Obviously, TMTOWTDI applies here, but the Perl FAQ recommends not using grep just to print. It is still a Perl-ish idiom - which is why the FAQ mentions it, I think: trying to discourage a bad habit.
The problem is that grep builds a return list, regardless of the context. This means you're making Perl go to the trouble of building a list that you then just throw away. If the list is large, you waste both time and space. If your intent is to iterate over the list, then use a for loop for this purpose.
In perls older than 5.8.1, map suffers from this problem as well. But since 5.8.1, this has been fixed, and map is context aware - in void context, no lists are constructed.
My sense is that true for loops are avoided in Perl and foreach loops are used instead. (The trick there is that you can write for even when you mean foreach. The interpreter figures it out based on the syntax of the loop.) So for your original question - you wanted to start at 11 - and your follow up - you only want even numbers, I think an array slice @array[x..y] and a foreach loop with an if is the way to go:
Code:
#!/usr/bin/perl
use strict;
use warnings;
my @testAr = 6 .. 40;
for my $num (@testAr[5..19]) {
if (($num % 2) == 0 ) {
print "$num\n";
}
}
But I'm still learning Perl myself, so maybe I have this all wrong.
Edit - if you are really curious (and bored), check this huge thread on whether or not to add a warning in Perl for the use of grep and map in a void context: http://www.nntp.perl.org/group/perl....msg131922.html
Last edited by Telemachos; 03-25-2008 at 07:45 AM.
Reason: Added Perl5.porters link
That’s all well and good, but exscape did not use grep in void context (the returned list is used as the argument of the for loop).
Hmm, I see what you mean but I'm still not sure. He created a new list, merely to iterate over it in the print statement, and then he threw the list out. My understanding of the FAQ is that this is exactly what they mean when they say, "This means you're making Perl go to the trouble of building a list that you then just throw away. If the list is large, you waste both time and space. If your intent is to iterate over the list, then use a for loop for this purpose." I'm not trying to be difficult (though maybe I'm being dense), but why isn't a slice + test more efficient here?
Hmm, I see what you mean but I'm still not sure. He created a new list, merely to iterate over it in the print statement, and then he threw the list out.
I guess you’re right. But you don’t necessarily have to throw out the list (I think there’s a trade-off between the number of function calls and unnecessary array duplication):
Code:
#!/usr/bin/perl
use strict;
use warnings;
my @testAr = 6 .. 40;
$,="\n";
print grep($_ % 2 == 0, @testAr), "";
Alternatively, you could do (the somewhat harder to read, but works if you use something other than print which takes only a single scalar argument):
Code:
#!/usr/bin/perl
use strict;
use warnings;
my @testAr = 6 .. 40;
$"="\n";
print "@{[grep($_ % 2 == 0,@testAr)]}\n";
In general, the benefit (or real power) of using grep is that it can easily be linked to other grep or map (or sort) calls. You don’t see it in this example, however.
Last edited by osor; 03-25-2008 at 09:14 PM.
Reason: add alternative that I thought of later
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.