首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何对嵌套在具有不同键的散列中的数组值进行排序?

如何对嵌套在具有不同键的散列中的数组值进行排序?
EN

Stack Overflow用户
提问于 2019-01-18 12:20:13
回答 2查看 82关注 0票数 1

我有一个html表,显示不同类型的停机的停机开始和结束时间。目前,我正在按停机类型对停机进行排序,但我希望能够按最早到最晚的开始时间对它们进行排序。每个开始和结束的时间都已经是按顺序的,但我正在尝试让它们按顺序排列,而不管是哪种类型。我知道对于按值排序,你通常使用某种排序的值比较,比如"sort { $h{$a} <=> $h{$b} } keys(%h);“

代码语言:javascript
复制
Currently they sort like:
1 | phone | 00:00:00 | 04:08:03
2 | phone | 14:26:03 | 18:00:00
3 | television | 12:34:19 | 12:34:25

But it should be like:
1 | phone | 00:00:00 | 04:08:03
2 | television | 12:34:19 | 12:34:25
3 | phone | 14:26:03 | 18:00:00

这是我的代码。

代码语言:javascript
复制
my %outages;

my @outage_times = qw(start end);

my %outage_reasons = (
  'tv' => 'television',
  'p' => 'phone'
);

foreach my $outage_reason (values %outage_reasons) {
  foreach my $outage (@outage_times) {
    $outages{$outage_reason}{$outage} = [];
  }
}

$outages{television}{start} = ['00:00:00', '14:26:03'];
$outages{television}{end} = ['04:08:03', '18:00:00'];
$outages{phone}{start} = ['12:32:02'];
$outages{phone}{end} = ['12:38:09'];

my $outage_number = 1;

foreach my $outage (sort keys %outages){
  for my $i (0 .. scalar (@{$outages{$outage}{start}})-1) {
    my $outage_start_time = $outages{$outage}{start}[$i];
    my $outage_end_time = $outages{$outage}{end}[$i];
    my $row_html = "<tr><td>$outage_number</td><td>$outage</td>";
        $row_html .= "<td>$outage_start_time</td>";
        $row_html .= "<td>$outage_end_time</td></tr>";
    $outage_number += 1;
  }
}
EN

回答 2

Stack Overflow用户

发布于 2019-01-18 18:34:52

我认为这是一种因为数据结构不必要地复杂而使自己的生活变得困难的情况。我不知道你的数据是从哪里来的,但如果你能得到像这样的散列数组,那会容易得多:

代码语言:javascript
复制
my @outages = ({
  type  => 'phone',
  start => '00:00:00',
  end   => '04:04:03',
}, {
  type  => 'phone',
  start => '14:26:03',
  end   => '18:00;00',
}, {
  type  => 'television',
  start => '12:34:19',
  end   => '12:34:25',
});

然后,排序和打印这些内容的代码就变得微不足道了。

代码语言:javascript
复制
my $number = 1;
for (sort { $a->{start} cmp $b->{start} } @outages) {
  my $row_html = '<tr>'
               . "<td>$number</td>"
               . "<td>$_->{type}</td>"
               . "<td>$_->{start}</td>"
               . "<td>$_->{end}</td>"
               . "</tr>\n";
  $number++;
  print $row_html;
}

值得注意的是,这只会起作用,因为您的时间戳可以被视为易于排序的字符串。如果时间戳比较复杂并且包含日期,那么您可能希望使用Time::PieceDateTime之类的东西将它们转换为可排序的数据。

我还想提一下,总有一天您会发现,在Perl代码中包含原始HTML标记会导致灾难。使用像Template Toolkit这样的模板系统要好得多。

票数 3
EN

Stack Overflow用户

发布于 2019-01-18 12:33:25

不要将时间戳存储为字符串,而应存储为自纪元以来的秒数。然后,您可以使用普通数值比较

代码语言:javascript
复制
foreach my $outage (sort { $a->{start} <=> $b->{start} values %outages) {

EDIT:用于任何语言/程序的时间戳处理的 SOP,除非您有一些非常特殊的要求:

  1. 解析输入格式以将时间戳转换为"X自纪元“
    • 始终转换为协调世界时,即。确定时区如果它不是input
    • Date::Manip提供的given
    • determine分辨率(秒、毫秒、微秒)可以是你的朋友here

  1. 在算法中以数值形式处理时间戳
    • 比较:a < b -> a发生在给定resolution

的时间戳之前

  1. 将时间戳转换为所需的输出格式

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54247718

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档