加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

如何从Perl中的单词列表的第一个字母生成一组范围?

发布时间:2020-12-15 23:23:06 所属栏目:大数据 来源:网络整理
导读:我不确定如何解释这个,所以我将从一个例子开始. 鉴于以下数据: AppleApricotBlackberryBlueberryCherryCrabappleCranberryElderberryGrapefruitGrapesKiwiMulberryNectarinePawpawPeachPearPlumRaspberryRhubarbStrawberry 我想根据我的数据的第一个字母生
我不确定如何解释这个,所以我将从一个例子开始.

鉴于以下数据:

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的字母开头.

我已经开始为此构建算法,但是我开始变得如此混乱.我不知道如何搜索谷歌这个 – 我不知道这个方法叫什么.

这是我开始的:

#!/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,1 ) );
    $index_frequency->{$first_letter}++;
}

foreach my $letter ( sort keys %{$index_frequency} ) {
    if ( $index_frequency->{$letter} ) {

        # build $ranges here
    }
}

我的问题是我继续使用一堆全局变量来跟踪计数和之前检查的字母 – 我的代码变得非常混乱非常快.

有人能给我一个正确的方向吗?我想这更像是一个算法问题,所以如果你没有办法在Perl中做到这一点,伪代码也会起作用,我想 – 我可以将它转换为Perl.

提前致谢!

解决方法

基本方法:

#!/usr/bin/perl -w
use strict;
use autodie;

my $PAGE_SIZE = 3;
my %frequencies;

open my $fh,'data';
while ( my $l = <$fh> ) {
    next unless $l =~ m{A([a-z])}i;
    $frequencies{ uc $1 }++;
}
close $fh;

my $current_sum = 0;
my @letters     = ();
my @pages       = ();

for my $letter ( "A" .. "Z" ) {
    my $letter_weigth = ( $frequencies{ $letter } || 0 );

    if ( $letter_weigth + $current_sum > $PAGE_SIZE ) {
        if ( $current_sum ) {
            my $title = $letters[ 0 ];
            $title .= '-' . $letters[ -1 ] if 1 < scalar @letters;
            push @pages,$title;
        }
        $current_sum = $letter_weigth;
        @letters     = ( $letter );
        next;
    }
    push @letters,$letter;
    $current_sum += $letter_weigth;
}
if ( $current_sum ) {
    my $title = $letters[ 0 ];
    $title .= '-' . $letters[ -1 ] if 1 < scalar @letters;
    push @pages,$title;
}

print "Pages : " . join( ",",@pages ) . "n";

问题在于它输出(来自您的数据):

Pages : A,B,C-D,E-J,K-O,P,Q-Z

但我认为这实际上是好方法:)你可以随时将for循环更改为:

for my $letter ( sort keys %frequencies ) {

如果你需要.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读