【问题标题】:How could I sort this hash array?我怎样才能对这个哈希数组进行排序?
【发布时间】:2018-12-06 04:20:56
【问题描述】:

我想按字母顺序对%hash{'name'} 的内容进行排序,以保持@{$hash{$keys}} 的其他元素的相关性。

我该怎么做?

my %hash = (
    date => [
        qw(
            2018/01/12
            2018/03/01
            2018/03/20
            2018/04/04
        )
    ],
    time => [
        qw(
            03:00:02
            01:00:01
            00:24:39
            11:33:33            
        )
    ],
    name => [
        qw(
            jerry
            tom
            micky
            agata            
        )
    ]
);

期望的输出:

date;time;name
2018/04/04;11:33:33;agata
2018/01/12;03:00:02;jerry
2018/03/20;00:24:39;micky
2018/03/01;01:00:01;tom

我还没有尝试过任何东西,因为我不知道从哪里开始。

【问题讨论】:

  • 请包括预期的输出,并告诉我们您是否已经尝试过任何东西。你可以edit你的问题。
  • 我没有尝试这样做,因为在网上我只找到了某种键列表:(或某种单一数组。也许在 perl 中不可能做到这一点?:(
  • 您不是软件开发人员,是吗?不要就这样放弃。几乎任何语言都有可能。在这种情况下,语言实际上与解决方案无关。这是一个难题。您的数据结构不理想。如果将数据转换为不同的结构,问题就会变得简单得多。
  • 所以你想要的输出是一个 CSV 文件。也许您的输入也是 CSV?这会让事情变得容易得多。您是如何获得%hash 的?考虑行,而不是列。
  • 但是在你阅读的时候它就在一行中?您为什么决定使用列?

标签: perl


【解决方案1】:

我选择此解决方案是因为我想在脚本中按日期进行另一种排序。有了关键参考,它会更聪明......

这是您问题的核心部分。您的想法是正确的,但是您以错误的方式实现了它。这就是现在让你陷入困境的原因。

让我们先看看您的数据。你说它是一个日志文件,所以它是基于行的。这个格式我已经编好了。

On 2018/01/12 at 03:00:02 user jerry did stuff.
On 2018/03/01 at 01:00:01 user tom did stuff.
On 2018/03/20 at 00:24:39 user micky did stuff.
On 2018/04/04 at 11:33:33 user agata did stuff.

您的预期输出是 CSV 文件。同样,这是基于行的。

date;time;name
2018/04/04;11:33:33;agata
2018/01/12;03:00:02;jerry
2018/03/20;00:24:39;micky
2018/03/01;01:00:01;tom

因此,您希望数据所在的结构仍然是基于行的。

当您想要按任何列对这些数据进行排序时,您将根据列中的值对 进行排序。因此,您确实希望以一种可以轻松访问该行的每个单独列的值的方式存储行。当您在电子表格中查看时,这一点会变得特别清楚。

每一列都是一行的一个值。所以让我们这样做吧。

my @events; # or something like that
while (my $row = <$log_fh>) {
    my ( $date, $time, $name ) = parse_row($row); # we don't care about this implementation

    push @events, {
        date => $date,
        time => $time,
        name => $name,
    };
}

现在我们有了这个数据结构(我用Data::Printer 输出)。

[
    [0] {
        date   "2018/01/12",
        name   "jerry",
        time   "03:00:02"
    },
    [1] {
        date   "2018/03/01",
        name   "tom",
        time   "01:00:01"
    },
    [2] {
        date   "2018/03/20",
        name   "micky",
        time   "00:24:39"
    },
    [3] {
        date   "2018/04/04",
        name   "agata",
        time   "11:33:33"
    }
]

如您所见,每行有一个哈希引用,其中包含一个日期键、一个时间键和一个名称键。

现在我们可以对这些结构中的任何键进行排序。 That's easy.

my @events_by_name = sort { $a->{name} cmp $b->{name} } @events;
my @events_by_date = sort { $a->{date} cmp $b->{date} } @events;
my @events_by_time = sort { $a->{time} cmp $b->{time} } @events;

然后您可以为每个文件生成 CSV 文件。

open my $fh, '>', 'events_by_name.csv' or die $!;
foreach my $event (@events_by_name) {
    print $fh join ';', $event->{name}, $event->{date}, $event->{time};
    print $fh "\n";
}
close $fh;

或者您可以根据事件的数量进行迭代,同时打开几个并且只循环一次。

open my $fh_name, '>', 'events_by_name.csv' or die $!;
open my $fh_date, '>', 'events_by_date.csv' or die $!;
for (my $i = 0; $i < @events_by_name; $i++) {
    print $fh_name join(
         ';', 
         @events_by_name->[$i]->{name}, 
         @events_by_name->[$i]->{date}, 
         @events_by_name->[$i]->{time},
    ); 
    print $fh_name "\n";

    print $fh_date join(
         ';', 
         @events_by_name->[$i]->{name}, 
         @events_by_name->[$i]->{date}, 
         @events_by_name->[$i]->{time},
    ); 
    print $fh_date "\n";
}
close $fh_name;
close $fh_date;

您可以通过使用另一个循环来进一步缩短它。

open my $fh_name, '>', 'events_by_name.csv' or die $!;
open my $fh_date, '>', 'events_by_date.csv' or die $!;
for (my $i = 0; $i < @events_by_name; $i++) {
    foreach my $fh ($fh_name, $fh_date) {
        print $fh join(
             ';', 
             @events_by_name->[$i]->{name}, 
             @events_by_name->[$i]->{date}, 
             @events_by_name->[$i]->{time},
        ); 
        print $fh "\n";
    }
}
close $fh_name;
close $fh_date;

如您所见,在处理线条时保持结构基于线条会更有意义。

【讨论】:

  • 我现在怎么亲你?你发的很清楚
  • @Perler 不需要。乐意效劳。我试图专注于实际的、潜在的问题,而不是直接的问题。初学者通常不知道要问什么问题。这是您将随着时间的推移而发展的众多技能之一。 // 您可能想查看How to Ask,看看如果有答案可以解决您的问题,该怎么做。 :)
  • @simbabque 我已将您的答案作为解决方案 :) 。为了打印我排序的键数组,我要纠正什么? print "-- 日期 --|--- 时间 ---|-- 名称 --\n"; #HEAD of List for (my $i=0; $i
  • @perler 你搞错了。我会更新答案并添加。
  • @simbabque,谢谢我已经编译了脚本,它运行良好
猜你喜欢
  • 2018-03-26
  • 1970-01-01
  • 2023-03-23
  • 2021-09-17
  • 1970-01-01
  • 2020-01-23
  • 2017-06-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多