我不确定如何准确地解释这个问题,因此我将从一个例子开始。
给定以下数据:
Apple
Apricot
Blackberry
Blueberry
Cherry
Crabapple
Cranberry
Elderberry
Grapefruit
Grapes
Kiwi
Mulberry
Nectarine
Pawpaw
Peach
Pear
Plum
Raspberry
Rhubarb
Strawberry
我希望根据数据的首字母生成索引,但我想把字母分组在一起。以下是上述数据集中首字母的频率:
2 A
2 B
3 C
1 E
2 G
1 K
1 M
1 N
4 P
2 R
1 S
由于我的示例数据集很小,我们只需假设将字母组合在一起的最大数量为3。使用上面的数据,我的索引将如下所示:
A B C D-G H-O P Q-Z
点击“D-G”链接将显示:
Elderberry
Grapefruit
Grapes
在我的范围列表中,我涵盖了整个字母表 - 我猜这并不完全必要 - 我也可以接受以下输出:
A B C E-G K-N P R-S
显然,我的数据集不是水果,我将拥有更多的数据(大约1000-2000个项目),我的“每个范围的最大值”将超过3。
我也不太担心不平衡的数据 - 因此,如果我的40%数据以“S”开头,则“S”将有自己的链接 - 我不需要按数据的第二个字母进行细分。
由于我的数据集不会经常更改,所以我可以使用静态的“每个范围的最大值”,但动态计算这个值也很好。此外,数据集不会以数字开头 - 保证以A-Z中的字母开头。
我已经开始构建这个算法,但它变得非常混乱,我只能重新开始。我不知道如何在Google上搜索这个 - 我不确定这个方法叫什么名字。
以下是我开始使用的内容:
#!/usr/bin/perl
use strict;
use warnings;
my $index_frequency = { map { ( $_, 0 ) } ( 'A' .. 'Z' ) };
my $ranges = {};
open( $DATASET, '<', 'mydata' ) || die "Cannot open data file: $!\n";
while ( my $item = <$DATASET> ) {
chomp($item);
my $first_letter = uc( substr( $item, 0, 1 ) );
$index_frequency->{$first_letter}++;
}
foreach my $letter ( sort keys %{$index_frequency} ) {
if ( $index_frequency->{$letter} ) {
# build $ranges here
}
}
我的问题是我一直在使用一堆全局变量来跟踪计数和先前检查过的字母 - 我的代码很快就会变得非常混乱。
有人能给我指点迷津吗?我猜这更像是一个算法问题,所以如果你没有一种在Perl中实现它的方法,伪代码也可以,我可以将其转换为Perl。
提前感谢!
my %index_frequency
会更好。这样你就不必写if($index_frequency....
了。 - Brad Gilbert