Perl排序字符串

时间:2014-11-17 17:46:41

标签: perl hash

我正在尝试根据字符串中包含的元音对文本文件中的小写字符串进行排序。

例如: vowel1将是出现在string1中的元音的子串,而vowel2则是相应的 string2的子串。如果子串vowel1以递增的ASCII顺序出现在vowel2之前,则string1出现在输出中的string2之前。

我试图通过哈希表来实现这一点,因为它听起来像是最有意义的数据结构。

我的代码:

#!/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";
    }
}

编译程序时,这就是结果。

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.

我仍然是Perl的新手,但仍然对一些你可以做但不能做的事情感到困惑。 对于哈希引用错误,我认为您可以使用%来引用它。我见过用数组做的代码。

我知道$w未初始化,但该案例的价值并不重要。

有没有比我这样做更好的方法呢?

非常感谢任何帮助。

编辑(样本数据):

如果我有一个包含这些词的文本文件

albatross,
apparate,
fanfare,
candelabra,
panacea,
vermeil,
parmesan,
albacore,
false,
beans,

订单应该是:

apparate,
fanfare,
panacea,
albatross,
albacore,
false,
parmesan,
candelabra,
beans,
vermeil

2 个答案:

答案 0 :(得分:4)

好的,我正在尝试这个:

#!/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

关键点是 - 自定义排序子返回-1,0或+1到sort。它会在内部接受任何逻辑。所以我们插入$a$b(特殊排序变量)。删除“非元音”&#39;并使用perl cmp函数进行比较。

答案 1 :(得分:2)

采用Sobrique的解决方案,以下是如何使用输入文件进行操作而不是传入<DATA>,非常简单:

#!/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;