perlynewby has asked for the wisdom of the Perl Monks concerning the following question:

Ok, I need a bit of advice on how to attack this problem. I will construct the loop but need a little bit of help with proper syntax

assume, I got a substring and, a part of that str (like maybe 2 letters to 9 letters) can match an already existing key in a hash.

1. what I am unsure about is how to check each character in the string (substring) against the key in hash. proper syntax

2. what is the key if not provided to me yet , how to check this...

#implement learnings: #substring matching ~~ #incremental substring match against a key that may not be given yet. +return 0 learning... #maybe add counter of the times the substring match a key use strict; use warnings; use diagnostics; my %match: my @char; my $str = 'abcdefghjki'; #substr could match a 2 letter key or 10 letter to a hash key... my @char = split //, $str; #assigned string into array to check foreach my $key (keys %match){ if($match->[0] ~~ @char) # i don't know how to check an incremental t +est for the substring against the key in hash.don't know proper synta +x. { #do something } } #return num of times sub finds in for my $keys ($keys){ $match{$keys}++; print "this is the number of times we see for $keys :",$match{$k +ey},"\n"; }

Replies are listed 'Best First'.
Re: find a substring of unknown length if it is in a hash
by Eily (Monsignor) on Jun 29, 2015 at 09:20 UTC

    Providing some code is a good start, but please try to write something that compiles (if you did manage to compile your code, this means you didn't actually use strict). What you are looking for is the index function (although a regex would also work, but index is easier to use and understand).

    if (-1 != index $str, $key) { # Do something }

Re: find a substring of unknow lenght if it is in a hash
by NetWallah (Canon) on Jun 29, 2015 at 13:20 UTC
    For searching, or filtering a list (keys %match is a list), perl's grep function is your friend.

    Using grep, will result in shorter code.

            "Despite my privileged upbringing, I'm actually quite well-balanced. I have a chip on both shoulders."         - John Nash

Re: find a substring of unknow lenght if it is in a hash
by stevieb (Canon) on Jun 29, 2015 at 13:48 UTC

    What you've done in your code is create an array with each element only one character in length, so when you use ~~ smartmatch against the array, you're only testing against a substring of a single character.

    If I understand what you're attempting to do, this code may help get you on your way:

    #!/usr/bin/perl use warnings; use strict; my $str = 'abcdefghijkl'; my %match = (ab => 0, abcd => 0, xyz => 0,); for my $key (keys %match){ if ($str =~ /$key/){ $match{$key}++; } else { print "$key not found in $str\n"; } } for my $k (keys %match){ print "key: $k value: $match{$k}\n"; }

    -stevieb

Re: find a substring of unknow lenght if it is in a hash
by perlynewby (Scribe) on Jun 29, 2015 at 19:53 UTC

    I need help understanding a warning I got and correct my syntax on the ~~ operator match.

    Also, I appreciate any commnents on the code and method(improving, provide possible oversight on code, etc..)

    Again, I am learning so much with all of your help and advice

    find myself liking Perl...today ;-)

    question 1 I don't understand why on INDEX, the warning says $string is undef? and I also had to declare it again as "my" when I did on pragma.

    question 2 whys is the '~~" operator method it's not working

    use strict; use warnings; use diagnostics; my @char; my $art; my $string = 'abcdefghijk'; my %match = (bc => "Michelangelo", efg => "Raffaello",de => "Caravaggi +o",ijk => "Tintoretto",hij=>"Leonardo",); @char = split //,$string; #check that the substring is in hash; foreach $art (keys %match){ if ($string=~/$art/){ print "There's a match in the string to $art =>", $match{$art}++ +,"\n"; } } #now using GREP foreach $art (keys %match){ if (my $seen= grep {$string =~ $art}$match{$art}) { print "I have seen using GREP $art=>",$match{$art},"\n"; } } #using ~~ match operator foreach $art (keys %match){ print "this is \~~ $art=> ",join('',$match{$art}) if /$string/i ~~$art +; } #using INDEX() foreach $art (keys %match){ print "this is INDEX $art =>",join('',$match{$art}),"\n", if index + my $tring,$art; }

      G'day perlynewby,

      "question 1 I don't understand why on INDEX, the warning says $string is undef? and I also had to declare it again as "my" when I did on pragma."

      When you get a error (or warning), it's vitally important that you paste it verbatim, not just type in a vague facsimile of the message.

      I strongly suspect that the error you got didn't mention $string at all; instead, it made reference to $tring! (Note the missing 's'.)

      So, to fix, add the 's' and remove the my (which you added).

      "question 2 whys is the '~~" operator method it's not working"

      That's the smart-match operator. It's experimental and subject to change. I recommend you learn non-experimental Perl before delving into ~~.

      -- Ken

        thank you

        I will add the error message it returns next time....Idon't know how my eyes missed that "s"...I spent time so much time trying to understand the error before asking. but ,now that you've pointed it out , I can see it clearly on the error message

        Use of uninitialized value $tring in index at C:\Users\Alberto\Documents\NetBeansProjects\PerlProject\Perl Essen +tials\hash_ref\partial_hash_check.pl line 49 (#3

        yeap, message said it was experimental too but I didn't actually understood that it may nt work...WILL stick with your advice.

        grazie

        Now, I have a question on WHY index worked at all? yes, I got an error while typing $string variable(skipped the "s" in code). however, I got an output anyways?

        so i went back and replicated the error so you can see it..again

        my $string = 'abcdefghijk'; my %match = (bc => "Michelangelo", efg => "Raffaello",de => "Caravaggi +o",ijk => "Tintoretto",hij=>"Leonardo",); foreach $art (keys %match){ print "this is INDEX $art =>",join(',',$match{$art}),"\n", if inde +x my $tring,$art; }
        Parentheses missing around "my" list at C:\Users\Alberto\Documents\NetBeansProjects\PerlProject\Perl Essen +tials\hash_ref\partial_hash_check.pl line 48 (#1) (W parenthesis) You said something like my $foo, $bar = @_; when you meant my ($foo, $bar) = @_; Remember that "my", "our", "local" and "state" bind tighter than c +omma. Use of uninitialized value $tring in index at C:\Users\Alberto\Documents\NetBeansProjects\PerlProject\Perl Essen +tials\hash_ref\partial_hash_check.pl line 48 (#2) (W uninitialized) An undefined value was used as if it were alread +y defined. It was interpreted as a "" or a 0, but maybe it was a mi +stake. To suppress this warning assign a defined value to your variables. To help you figure out what was undefined, perl will try to tell y +ou the name of the variable (if any) that was undefined. In some cas +es it cannot do this, so it also tells you what operation you used th +e undefined value in. Note, however, that perl optimizes your progr +am and the operation displayed in the warning may not necessarily app +ear literally in your program. For example, "that $foo" is usually optimized into "that " . $foo, and the warning will refer to the concatenation (.) operator, even though there is no . in your program. this is INDEX efg =>Raffaello this is INDEX de =>Caravaggio this is INDEX hij =>Leonardo this is INDEX bc =>Michelangelo this is INDEX ijk =>Tintoretto