When I apply String::Approx to the values taken from the database, it doesn't check the matching words.
The program is as follows...
use String::Approx qw (amatch);
my #matches = qw();
my %matchhash = qw();
my #x=$search_keyword;
my $i=0;
my $j=0;
my $l=1;
my $qry1="SELECT * FROM AuctionCategoriesName";
my $prp1 = $dbh1->prepare($qry1);
$prp1->execute();
while(my $row1=$prp1->fetchrow_hashref())
{
$y=$row1->{'Name'};
#name="(['$y'])";
#match = grep { amatch (#x, #$_) } #name;
$cnt=$#match;
if($cnt < 1)
{
$matches[$i]=$match[0];
$i++;
}
}
Connections to db are perfect.
I want to get the approximately matched names from db amoung all the values present in the $row1->{'Name'}. The values must be kept stored in $matches[$i]. I call those values as:
foreach my $k (#matches) { print "$k <br/>" }
As Richard said this line is unnecessary :-
#name="(['$y'])";
You could write $y as is and perl does the right thing.
The grep followed by the if is duplication of the same work. amatch returns true/false in scalar context so we can use that.
You could simplify your code along these lines :-
1 use String::Approx qw (amatch);
2 use strict;
3 my #matches = qw();
4 my $search_keyword = 'Hello';
5 foreach my $y ('hello', 'world')
6 {
7 if (amatch ($search_keyword, ($y)))
8 {
9 push #matches, $y;
10 }
11 }
12
13 print #matches
The output is :-
$ perl test.pl
hello
Related
sub Solution{
my $n=$_[0];
my $m=lc $_[1];
my #chars=split("",$m);
my $result=0;
my #vowels=("a","e","i","o","u");
#OUTPUT [uncomment & modify if required]
for(my $i=0;$i<$n;$i=$i+1){
for(my $j=0;$j<5;$j=$j+1){
if($chars[$i]==$vowels[$j]){
$result=$result+1;
last;
}
}
}
print $result;
}
#INPUT [uncomment & modify if required]
my $n=<STDIN>;chomp($n);
my $m=<STDIN>;chomp($m);
Solution($n,$m);
So I wrote this solution to find the number of vowels in a string. $n is the length of the string and $m is the string.
However, for the input 3 nam I always get the input as 3.
Can someone help me debug it?
== compares numbers. eq compares strings. So instead of $chars[$i]==$vowels[$j] you should write $chars[$i] eq $vowels[$j]. If you had used use warnings;, which is recommended, you'd have gotten a warning about that.
And by the way, there's no need to work with extra variables for the length. You can get the length of a string with length() and of an array for example with scalar(). Also, the last index of an array #a can be accessed with $#a. Or you can use foreach to iterate over all elements of an array.
A better solution is using a tr operator which, in scalar context, returns the number of replacements:
perl -le 'for ( #ARGV ) { $_ = lc $_; $n = tr/aeiouy//; print "$_: $n"; }' Use Perl to count how many vowels are in each string
use: 2
perl: 1
to: 1
count: 2
how: 1
many: 2
vowels: 2
are: 2
in: 1
each: 2
string: 1
I included also y, which is sometimes a vowel, see: https://simple.wikipedia.org/wiki/Vowel
Let me suggest a better approach to count letters in a text
#!/usr/bin/env perl
#
# vim: ai:ts=4:sw=4
#
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my $debug = 0; # debug flag
my %count;
my #vowels = qw/a e i o u/;
map{
chomp;
my #chars = split '';
map{ $count{$_}++ } #chars;
} <DATA>;
say Dumper(\%count) if $debug;
foreach my $vowel (#vowels) {
say "$vowel: $count{$vowel}";
}
__DATA__
So I wrote this solution to find the number of vowels in a string. $n is the length of the string and $m is the string. However, for the input 3 nam I always get the input as 3.
Can someone help me debug it?
Output
a: 7
e: 18
i: 12
o: 12
u: 5
Your code is slightly modified form
#!/usr/bin/env perl
#
# vim: ai:ts=4:sw=4
#
use strict;
use warnings;
use feature 'say';
my $input = get_input('Please enter sentence:');
say "Counted vowels: " . solution($input);
sub get_input {
my $prompt = shift;
my $input;
say $prompt;
$input = <STDIN>;
chomp($input);
return $input;
}
sub solution{
my $str = lc shift;
my #chars=split('',$str);
my $count=0;
my #vowels=qw/a e i o u/;
map{
my $c=$_;
map{ $count++ if $c eq $_} #vowels;
} #chars;
return $count;
}
I have been trying to find values that match between two columns (columns a and column b) of a large file and print the common values, plus the corresponding column d. I have been doing this by interating through hashes, however, because the file is so large, there is not enough memory to produce the output file. Is there any other way to do the same thing using less memory resources.
Any help is much appreciated.
The script I have written thus far is below:
#!usr/bin/perl
use warnings;
use strict;
open (FILE1, "<input.txt") || die "$!\n Couldn't open input.txt\n";
open (Output, ">output.txt")||die "Can't Open output.txt ";
my $hash1={};
my $hash2={};
while (<FILE1>) {
chomp (my $line=$_);
my ($a, $b, $c, $d) = split (/\t/, $line);
if ($a) {
$hash1->{$a}{info1} = "$d"; #original_ID-> YOB
}
if ($b) {
$hash2->{$b}{info2} = "$a"; #original_ID-> sire
}
foreach my $key (keys %$hash2) {
if (exists $hash1{$a}) {
$info1 = $hash1->{$a}->{info1};
print "$a\t$info1\n";
}
}
}
close FILE1;
close Output;
print "Done\n";
To clarify, the input file is a large pedigree file. An example is:
1 2 3 1977
2 4 5 1944
3 4 5 1950
4 5 6 1930
5 7 6 1928
An example of the output file is:
2 1944
4 1950
5 1928
Does the below work for you ?
#!/usr/local/bin/perl
use strict;
use warnings;
use DBM::Deep;
use List::MoreUtils qw(uniq);
my #seen;
my $db = DBM::Deep->new(
file => "foo.db",
autoflush => 1
);
while (<>) {
chomp;
my #fields = split /\s+/;
$$db{$fields[0]} = $fields[3];
push #seen, $fields[1];
}
for (uniq #seen) {
print $_ . " " . $$db{$_} . "\n" if exists $$db{$_};
}
This is my program , I want to let user type a matrix line by line and print the while matrix , but I can't see the matrix
The user will type
1 2 3
4 5 6
7 8 9
like this
and I want to let it show
1 2 3
4 5 6
7 8 9
Perl program
$Num = 3;
while($Num > 0 )
{
$Row = <STDIN>;
$Row = chomp($Row);
#Row_array = split(" ",$Row);
push #P_matrix , #Row_array;
#Row_array = ();
$Num = $Num - 1;
}
for($i=0;$i<scalar(#P_matrix);$i++)
{
for($j=0;$j<scalar(#P_matrix[$i]);$j++)
{
printf "$d ",$P_matrix[$i][$j];
}
print "\n";
}
I change the expression => printf "$d ",$P_matrix[$i][$j]; to print $P_matrix[$i][$j]
but still don't work.
To create a multi-dimensional array, you have to use references. Use
push #P_matrix, [ #Row_array ];
to create the desired structure.
Also, chomp does not return the modified string. Simply use
chomp $Row;
to remove a newline from $Row. Moreover, chomp is not needed at all if you split on ' '.
printf uses % as the formatting character, not $.
You can use Data::Dumper to inspect complex data structures. Use strict and warnings to help you avoid common problems. Here is how I would write your program:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my #p_matrix;
push #p_matrix , [ split ' ' ] while <>;
warn Dumper \#p_matrix;
for my $i (0 .. $#p_matrix)
{
for my $j (0 .. $#{ $p_matrix[$i] })
{
printf '%d ', $p_matrix[$i][$j];
}
print "\n";
}
First and foremost please use use strict; use warnings;
Issues in your code:
You have a single dimensional array, but your are trying to access
it like two dimensional array. In order to make 2 dimensional array push the array reference of Row_array in #P_matrix as [#Row_array].
Where is $d defined? declare $d as my $d or our $d if you mean $d as scalar variable.
OR
For using %d, use need sprintf. Please read this.
In Bash, seq 5 5 20 produces 5 10 15 20.
In Perl, 1..5 produces 1 2 3 4 5; does it support step?
How do I produce a range with step in Perl?
perldoc -f map is one way:
use warnings;
use strict;
use Data::Dumper;
my #ns = map { 5 * $_ } 1 .. 4;
print Dumper(\#ns);
__END__
$VAR1 = [
5,
10,
15,
20
];
See also: perldoc perlop
The range operator in Perl doesn't support steps. You could use a for loop instead:
for (my $i = 5; $i <= 20; $i += 5) {
print "$i\n";
}
The List::Gen range function does this:
use strict;
use warnings;
use feature 'say';
use List::Gen;
my $range = range 5, 20, 5;
say for #$range; # 5
# 10
# 15
# 20
say while <$range>; # TIMT1WTDI
$range->say; # TAMT2WTDI, v.0.974
say $range->str; # TAMT3WTDI, v.0.974
my $by_fives = <5 .. 20 by 5>;
say while <$by_fives>; #TAMT4WTDI
<5 .. * by 5>->say( 4 ); #TAMT5WTDI
Not as good as toolic's answer:
use warnings;
use strict;
my #ns;
for my $n (1..4) {
push(#ns, $n*5);
}
I wrote Acme::Range::Module a while back as a gag module - hence the Acme:: namespace - but it does do what you want and has tests and is supported. Here's the example code:
use Acme::Globule qw( Range );
foreach (<10..1>) {
print "$_... ";
}
print "Lift-off!\n";
# put down that crack pipe...
sub my_keys(\%) {
my #hash = %{ $_[0] };
return #hash[ glob("0,2..$#hash") ];
}
sub my_values(\%) {
my #hash = %{ $_[0] };
return #hash[ glob("1,3..$#hash") ];
}
Here is an easy solution that utilizes map and the built-in range operator:
sub range {
my ($start, $end, $step) = #_;
$step ||= 1;
return map { $_ * $step } ($start / $step .. $end / $step);
}
Notice the key point here is the map {} block. We simply divide the end
by the given step (works for negative and positive) then map each value
to the multiple of the given step.
Like the map solution :)
Here it is used to look for files starting with even numbers in a range 116 to 648:
perl -e 'foreach (map { 2 * $_ } (116/2) .. (648/2)) { system("ls -l $_*"); } '
Perl is just wonderful for some jobs and making funny one-liners :)
I have a program that prints out the location of commas in a paragraph of text in the form
For example if the paragraph is
one,two,three
three and a half
four,five
six
seven,eight
The program will print
0:4
0:8
2:5
4:6
I would like to use this output to create an array where the numbers after the colon are listed across columns in the row specified by the index before the colon. The array formed by the coordinates above would be
4 8
<blank or character '.'>
5
<blank or character '.'>
6
so array[0,0] = 4, array[0,1] = 8
array[1,0] = empty
array[2,0] = 5
etc...
I bet this is simple but I need help to write it.
$data_file="file.out";
open(DAT, $data_file) || die("Could not open file!");
#raw_data=<DAT>;
close(DAT);
my %array;
my $line = 0;
foreach $newline(#raw_data) {
chomp;
while ( $newline=~m/(,|;|:|and)/) {
push #{ $array{$line} }, pos($newline); # autovivification
}
$line++; }
Program
#!/usr/bin/env perl
use strict;
use warnings;
my %array;
my $line = 0;
while (<DATA>) {
chomp;
while ( /(,|;|:|(?:and))/g ) {
my $position = pos() - length($1) + 1;
push #{ $array{$line} }, $position; # autovivification
}
$line++;
}
for ( sort { $a <=> $b } keys %array ) {
my $flattened_value = join ', ', #{ $array{$_} };
print "$_ -> $flattened_value\n";
}
__DATA__
one,two,three
three and a half
four,five
six
seven,eight
Output
0 -> 4, 8
1 -> 7
2 -> 5
4 -> 6
Refer: chomp, join, keys, sort, split.
Refer the following documents to get an understanding of Perl's data structures and especially autovivification which has been used in this example.
perldoc perlref
perldoc perlreftut