MipsMoreLikeWhips
MipsMoreLikeWhips

Reputation: 147

Perl Sorting Character Strings

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

Answers (2)

chomp
chomp

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

Sobrique
Sobrique

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

Related Questions