Reputation: 147
I am trying to sort lowercase strings from a text file based on the vowels contained in the string.
For Example: vowel1 will be the substring of vowels appearing in string1, and vowel2 the corresponding substring of string2. If the substring vowel1 appears before vowel2 in the ascending ASCII order,string1 appears before string2 in the output.
I am trying to do this through a hash table as it sounds like the data structure that makes the most sense.
My code:
#!/usr/bin/perl -w
use strict;
my %hash;
my $vow = my $w;
my $file = $ARGV[0];
open (IN, $file) or die "Could not open file: $!";
while (my $line = <IN>) {
$vow = ~s/[^aeiou]//g;
$hash{$vow}{$w} = 1;
}
close(IN);
foreach my $key (sort %hash) {
foreach my $word (sort %{$hash {$key}}){
print "$word\n";
}
}
When I compile the program this is the results.
Use of uninitialized value $_ in substitution (s///) at sort_strings.pl line 14, <IN> line 1.
Use of uninitialized value $w in hash element at sort_strings.pl line 16, <IN> line 1.
Can't use an undefined value as a HASH reference at sort_strings.pl line 23.
I am still new to Perl and still get confused on some the things you can and cannot do. For the hash reference error I thought you could just reference it by using a %. I have seen code that does that with arrays.
I know that $w
is uninitialized, but the value for that case does not matter.
Is there a better way to do this than the way I am doing it?
Any help is greatly appreciated.
Edit (Sample Data):
If I have a text file with these words
albatross,
apparate,
fanfare,
candelabra,
panacea,
vermeil,
parmesan,
albacore,
false,
beans,
The order should be:
apparate,
fanfare,
panacea,
albatross,
albacore,
false,
parmesan,
candelabra,
beans,
vermeil
Upvotes: 2
Views: 313
Reputation: 125
Taking Sobrique's solution, here's how to do it with an input file as you wanted to do instead of passing in <DATA>
, pretty simple :
#!/usr/bin/perl -w
use strict;
use warnings;
open my $INFILE, '<', $ARGV[0] or die $!;
sub sort_vowelsonly {
my $a_vowels = $a;
my $b_vowels = $b;
$vowels_a =~ s/[^aeiou]//g;
$vowels_b =~ s/[^aeiou]//g;
return $a_vowels cmp $b_vowels;
}
print sort { sort_vowelsonly } <$INFILE>;
close $INFILE;
Upvotes: 2
Reputation: 53498
OK, I'm trying this:
#!/usr/bin/perl
use strict;
use warnings;
sub sort_vowelsonly {
my $a_vowels = $a;
my $b_vowels = $b;
$a_vowels =~ s/[^aeiou]//g;
$b_vowels =~ s/[^aeiou]//g;
print "DEBUG: Comparing $a_vowels with $b_vowels\n";
return $a_vowels cmp $b_vowels
}
print sort { sort_vowelsonly } <DATA>;
__DATA__
albatross
apparate
fanfare
candelabra
panacea
vermeil
parmesan
albacore
false
beans
Key point is - the custom sort sub returns -1, 0 or +1 to sort
. It'll accept any logic internally. So we insert $a
and $b
(special sort variables). Strip out the 'non vowels' and use the perl cmp
function to do the comparison.
Upvotes: 4