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

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Regex

 



zapzap
User

Feb 3, 2014, 12:37 PM

Post #1 of 7 (1292 views)
Regex Can't Post

I wanted to create subroutine such that the input of the subroutine is a string and what is returned is a string containing only those words that have vowels [aeiou] in alphabetical order.


Code
sub ordered { 
my $s = '';
for ( split(/ /,shift) ) {
$s .= "$_ " if $_ !~ /u.*?[aeio]|[ou].*?[aei]|[oui].*?[ae]|[eiou].*?a/;
}
$s;
}

# But I wanted it shorter
# My revised attempt only removes the portion of the
# word that is unordered. Even when I modified the regex
# with \b it didn't help

my $str = 'this is a vowel without a string'
$str =~ s/ \w*?u\w*?[aeio]|[ou]\w*?[aei]|[oui]\w*?[ae]|[eiou]\w*?a\w*? //;

# str should be 'this is a without a string'


TIA
zap


Kenosis
User

Feb 3, 2014, 4:27 PM

Post #2 of 7 (1276 views)
Re: [zapzap] Regex [In reply to] Can't Post


Code
sub orderedII { 
join ' ', grep { my @x = sort my @y = /[aeiou]/gi; "@x" eq "@y" } split ' ', shift;
}


As your subroutine does, the above splits the sent string on whitespace, and the resulting list is sent to grep. Within the code block, a regex grabs all of the vowels in a word (if any) and initializes @y with them, and those are passed to sort and the sorted vowels are stored in @x. When an array is placed within double-quotes, it's interpolated and acts like a string with (usually) a space between elements. One array is sorted; the other is not and it's elements--the vowels--are in the order in which they appear in the word. If the two interpolated arrays are equal, the vowels in the word are in alphabetical order, and the word is passed through grep and joined with a space. The result of the join, if any, is returned.

I assumed that you wanted to let 'words' pass if they didn't contain any vowels, even though your spec says "...only those words that have vowels [aeiou] in alphabetical order." If vowels are a requirement, you can use the following at the end of grep's code block:

Code
/[aeiou]/i and "@x" eq "@y"



(This post was edited by Kenosis on Feb 3, 2014, 10:35 PM)


zapzap
User

Feb 3, 2014, 5:29 PM

Post #3 of 7 (1266 views)
Re: [Kenosis] Regex [In reply to] Can't Post

Um, not too sure what you did there. Would you add a couple of comments so that I may dissect the approach?


Kenosis
User

Feb 3, 2014, 7:19 PM

Post #4 of 7 (1260 views)
Re: [zapzap] Regex [In reply to] Can't Post

My apologies. Will add comments below the code.


zapzap
User

Feb 4, 2014, 12:13 AM

Post #5 of 7 (1231 views)
Re: [Kenosis] Regex [In reply to] Can't Post

Thank you for the comments. They are very clear and understandable.

One more question, in general, regarding grep:

Rather, to clarify, for my understanding
Suppose we have...

Code
 
@array = grep { code } @another_array

If the 'code' portion resolves to 'true', the element currently 'passed' into grep is 'selected' and 'added' to @array?

I guess I'm asking because the line in your grep statement
"@x" eq "@y"
leads me (probably incorrectly) to believe that @x will be added to the @array (or even @y).

It would be awesome and have a profound impact on my perl if
within a grep block, if the code block resolves to true, then current element is selected to be added to the output (array).

Is that correct?

Anyways, your code is very good, and your explanations were even better!

Thanx again
zap



Kenosis
User

Feb 4, 2014, 10:17 AM

Post #6 of 7 (1206 views)
Re: [zapzap] Regex [In reply to] Can't Post

You're most welcome!

From grep's documentation:

Quote
[grep] Evaluates the BLOCK or EXPR for each element of LIST (locally setting $_ to each element) and returns the list value consisting of those elements for which the expression evaluated to true.

For example:

Code
use strict; 
use warnings;

my @arr = 0 .. 9;
my @odd = grep $_ % 2, @arr;
print "@odd";

Output:

Code
1 3 5 7 9

Thus, grep passes the current list element if and only if its block/expression is true.


Laurent_R
Veteran / Moderator

Feb 5, 2014, 10:12 AM

Post #7 of 7 (1193 views)
Re: [zapzap] Regex [In reply to] Can't Post

You have to distinbguish what is going on in the code block and in the grep function itself.

The code block ends with the statement comparing x and y. The code block returns TRUE to grep if x and y are equal and FALSE otherwise. If grep receives TRUE from the code block, it passes to the array on its left the $_ value received froml the array on its right; if grep receives FALSE from the code block, grep filters out the $_ value received from the array on its right. Of course, if the code block modifies $_, then grep will return to its left the modified $_ value (this is often a not so good idea, because modifying $_ also modifies the values in the original array on the right side.

 
 


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

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