'Instr Equivalent in perl?

A variable named RestrictedNames holds the list of restricted user names. SplitNames is an array variable which holds the complete set of user name. Now I have to check whether current name is found in RestrictedNames variable like using instr.

@SplitNames = ("naag algates","arvind singh","abhay avasti","luv singh","new algates") and now i want to block all the surnames which has "singh" ,"algates" etc.

    @SplitNames = ("naag algates","arvind singh","abhay avasti","luv singh","new algates")
    $RestrictedNames="tiwary singh algates n2 n3 n4 n5 n6";
    for(my $i=0;$i<@SplitNames;$i++)
    {
        if($RestrictedNames =~ m/^$SplitNames[$i]/ ) //google'd this condition, still fails
        {
              print "$SplitNames[$i] is a restricted person";
        }
    }


Solution 1:[1]

You should modify this line:

if($RestrictedNames =~ m/^$SplitNames[$i]/ )

to

if($RestrictedNames =~ m/$SplitNames[$i]/ )

^ looks for a match from the beginning.

For more details about perl metacharacters, see here

EDIT: If you need blocking based on surnames, try this code in the for-loop body.

my @tokens = split(' ', $SplitNames[$i]); # splits name on basis of spaces
my $surname = $tokens[$#tokens]; # takes the last token
if($RestrictedNames =~ m/$surname/ )
{
      print "$SplitNames[$i] is a restricted person\n";
}

Solution 2:[2]

Don't try dealing with a string of restricted names, deal with an array.

Then just use the smart match operator (~~ or two tilde characters) to see if a given string is in it.

#!/usr/bin/perl
use v5.12;
use strict;
use warnings;

my $RestrictedNames="n1 n2 n3 n4 n5 n6 n7 n8 n9";
my @restricted_names = split " ", $RestrictedNames;
say "You can't have foo" if 'foo' ~~ @restricted_names;
say "You can't have bar" if 'bar' ~~ @restricted_names;
say "You can't have n1" if 'n1' ~~ @restricted_names;
say "You can't have n1a" if 'n1a' ~~ @restricted_names;

Solution 3:[3]

Try something like below using Hash Slice:

my @users =  ( "n10", "n12", "n13", "n4", "n5" );
my @r_users = ( "n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9" ) ;
my %check;
@check{@r_users}  = ();
foreach my $user ( @users ) {
   if ( exists $check{$user} ) {
      print"Restricted User: $user  \n";
   }
}

Solution 4:[4]

Most idiomatic way would be to create a hash of the restricted names, then split the surname from the name and check if the surname is in the hash.

use strict;
use warnings;

my @SplitNames = ("naag algates","arvind singh","abhay avasti","luv singh","new algates");
my $RestrictedNames = "tiwar y singh algates n2 n3 n4 n5 n6";

# Create hash of restricted names
my %restricted;
map { $restricted{$_}++ } split(' ', $RestrictedNames);

# Loop over names and check if surname is in the hash
for my $name (@SplitNames) {
    my $surname = (split(' ', $name))[-1];
    if ( $restricted{$surname} ) {
        print "$name is a restricted person\n";
    }
}

Please note that the split function normally takes a RegEx. However using ' ' with split is a special case. It splits on any length of whitespace, and also ignores any leading whitespace, so it's useful for splitting strings of individual words.

FYI, the equivalent to instr in perl is to use index($string, $substring). If $substring does not occur inside $string it will return -1. Any other value means $string contains $substring. However, when comparing lists it's much less hassle to use a hash like I have shown above... and unlike index, it won't match 'joyce' when you really only meant to match 'joy'.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Quentin
Solution 3 Nikhil Jain
Solution 4