微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

perl使用数组对子字符串进行排序以确定排序顺序

如何解决perl使用数组对子字符串进行排序以确定排序顺序

我有以下形式的字符串列表:

CLUB1_20201008_EVE
CLUB1_20201008_AFT
CLUB1_20201008_AM
CLUB1_20201008_AM2
CLUB1_20201008_PM
CLUB1_20201008_NIGHT
CLUB2_20201008_EVE
CLUB2_20201008_AFT
CLUB2_20201008_AM
CLUB2_20201008_AM2
CLUB2_20201008_PM
CLUB2_20201008_NIGHT

我可以按俱乐部名称和日期进行排序,但是一天中的时间需要像AM,AM2,AFT,PM,EVE,NIGHT那样进行排序。这些显然是无法排序的,因为它们的顺序不是字母顺序的。

如何使用辅助数组使它们按正确的顺序排序?

谢谢,牛奶

预期输出 CLUB1_20201008_NIGHT CLUB2_20201008_NIGHT CLUB1_20201008_EVE CLUB2_20201008_EVE CLUB1_20201008_PM CLUB2_20201008_PM CLUB1_20201008_AFT CLUB2_20201008_AFT CLUB1_20201008_AM2 CLUB2_20201008_AM2 CLUB1_20201008_AM CLUB2_20201008_AM

解决方法

一种方法是使用哈希表将字符串映射到其数字顺序,然后基于该哈希表进行比较:

#!/usr/bin/env perl
use warnings;
use strict;
use feature qw/say state/;

my @clubs = qw/CLUB1_20201008_EVE CLUB1_20201008_AFT CLUB1_20201008_AM
CLUB1_20201008_AM2 CLUB1_20201008_PM CLUB1_20201008_NIGHT
CLUB2_20201008_EVE CLUB2_20201008_AFT CLUB2_20201008_AM
CLUB1_20201008_AM2 CLUB1_20201008_PM CLUB1_20201008_NIGHT/;

sub sort_clubs {
    state $mappings = { AM => 1,AM2 => 2,AFT => 3,PM => 4,EVE => 5,NIGHT => 6 };

    # For use with a Schwartzian Transform of the original data.
    # Expected format of arguments: [ [ club name,date,time ],original string ]
    my $cmp = $a->[0][0] cmp $b->[0][0];
    if ($cmp != 0) {
        return $cmp;
    }
    $cmp = $a->[0][1] <=> $b->[0][1];
    if ($cmp != 0) {
        return $cmp;
    } else {
        return $mappings->{$a->[0][2]} <=> $mappings->{$b->[0][2]}
    }
}

@clubs = map { $_->[1] } sort sort_clubs map { [ [ split(/_/,$_) ],$_ ] } @clubs;
say "@clubs";

如果您以前没有看到过用于排序的惯用语,则维基百科提供有关Schwartzian Transform的信息。

,

诀窍是在每个时间字符串和您可以排序的数字之间创建映射。

C:\Programming\Projects\ExampleSolution\ExampleProject\Uploads\

基于that's not guaranteed的解决方案将是最干净,最快的解决方案。

var/www/ExampleProject/Uploads

不带模块的简单解决方案:

my @shifts = qw( AM AM2 AFT PM EVE NIGHT );
my %shift_order = map { $shifts[$_] => $_ } 0..$#shifts;

不带模块的高性能解决方案:

use Sort::Key::Multi qw( ssukeysort );

my @shifts = qw( AM AM2 AFT PM EVE NIGHT );
my %shift_order = map { $shifts[$_] => $_ } 0..$#shifts;

my @sorted =
   ssukeysort {
      my ($club,$date,$shift) = split /_/;
      ( $club,$shift_order{$shift} )
   }
      @unsorted;
,

有很多方法可以达到预期的效果。

注意:假定您未尝试在俱乐部,date_hour_min和day_time上进行排序,因为代码未在您的问题中声明。所需的排序输出样本将有助于解决您的问题-我们无法理解您的想法。

请研究以下两种可能的方法。

您已根据字符串中的时间索引声明了排序顺序-让它以某种方式使用。为了简单起见,我将使用AM,AM2,AFT,PM,EVE,NIGHT作为初始化字符串。

第一种方法使用%order哈希,其中时间日期是表示数字顺序的键和数字。以数字顺序作为键存储在HoA中的字符串。填充完哈希后,只需按照数字键顺序打印行,并保留其在输入中的出现顺序即可。

use strict;
use warnings;
use feature 'say';

my $count = 0;
my @set   = split ',','AM,NIGHT';
my %order = map { $_ => $count++ } @set;
my %result;

while( <DATA> ) {
    chomp;
    for my $k ( keys %order ) {
        push @{$result{$order{$k}}},$_ if /_$k\z/;
    }
}

for( sort {$a <=> $b} keys %result ) {
    say for @{ $result{$_} };
}


__DATA__
CLUB1_20201008_EVE
CLUB1_20201008_AFT
CLUB1_20201008_AM
CLUB1_20201008_AM2
CLUB1_20201008_PM
CLUB1_20201008_NIGHT
CLUB2_20201008_EVE
CLUB2_20201008_AFT
CLUB2_20201008_AM
CLUB1_20201008_AM2
CLUB1_20201008_PM
CLUB1_20201008_NIGHT

输出

CLUB1_20201008_AM
CLUB2_20201008_AM
CLUB1_20201008_AM2
CLUB1_20201008_AM2
CLUB1_20201008_AFT
CLUB2_20201008_AFT
CLUB1_20201008_PM
CLUB1_20201008_PM
CLUB1_20201008_EVE
CLUB2_20201008_EVE
CLUB1_20201008_NIGHT
CLUB1_20201008_NIGHT

第二种方法更加简单。根据 time day 索引(在行末)在HoA %result中插入行。然后根据预定义的$order数组打印打印HoA。

use strict;
use warnings;
use feature 'say';

my @order = split ',NIGHT';
my %result;

while( <DATA> ) {
    chomp;
    push @{$result{$1}},$_ if /_([^_]+)\z/;
}

for( @order ) {
    say for @{ $result{$_} };
}


__DATA__
CLUB1_20201008_EVE
CLUB1_20201008_AFT
CLUB1_20201008_AM
CLUB1_20201008_AM2
CLUB1_20201008_PM
CLUB1_20201008_NIGHT
CLUB2_20201008_EVE
CLUB2_20201008_AFT
CLUB2_20201008_AM
CLUB1_20201008_AM2
CLUB1_20201008_PM
CLUB1_20201008_NIGHT

输出

CLUB1_20201008_AM
CLUB2_20201008_AM
CLUB1_20201008_AM2
CLUB1_20201008_AM2
CLUB1_20201008_AFT
CLUB2_20201008_AFT
CLUB1_20201008_PM
CLUB1_20201008_PM
CLUB1_20201008_EVE
CLUB2_20201008_EVE
CLUB1_20201008_NIGHT
CLUB1_20201008_NIGHT

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。