如何比较散列数组中的元素并仅保留最新的项目

时间:2012-06-11 18:55:35

标签: arrays perl hash

我正在使用下面的哈希数组,并且如果四个特定参数相同,我们只想根据'日期时间'显示最新的哈希值。让我用下面的代码提供一个例子......

如果玩具,善良,舞台,步骤'是相同的,然后我只想将那个哈希存储到一个新的哈希数组中。

原始哈希数组

$VAR1 = [
      {
        'Color' => 'green',
        '2nd Color' => 'blue',
        '3rd Color' => 'yellow',
        'toy' => 'truck',
        'toy_type' => 'ford',
        'kind' => '4door',
        'Stage' => 'Production',
        'Step' => 'Platform',
        'Datetime' => '2012/06/08 01:49:19'
      },
      {
        'Color' => 'red',
        '2nd Color' => 'green',
        '3rd Color' => 'yellow',
        'toy' => 'truck',
        'toy_type' => 'ford',
        'kind' => '4door',
        'Stage' => 'Production',
        'Step' => 'Platform',
        'Datetime' => '2012/06/08 01:46:17'
      },
      {
        'Color' => 'red',
        '2nd Color' => 'blue',
        '3rd Color' => 'green',
        'toy' => 'truck',
        'toy_type' => 'chevy',
        'kind' => '4door',
        'Stage' => 'Production',
        'Step' => 'Platform',
        'Datetime' => '2012/06/08 01:52:14'
      },
      {
        'Color' => 'red',
        '2nd Color' => 'blue',
        '3rd Color' => 'yellow',
        'toy' => 'truck',
        'toy_type' => 'chevy',
        'kind' => '4door',
        'Stage' => 'Production',
        'Step' => 'Platform',
        'Datetime' => '2012/06/08 01:24:14'
      },
      {
        'Color' => 'white',
        '2nd Color' => 'blue',
        '3rd Color' => 'yellow',
        'toy' => 'truck',
        'toy_type' => 'gmc',
        'kind' => '4door',
        'Stage' => 'Production',
        'Step' => 'Platform',
        'Datetime' => '2012/06/08 06:24:14'
      },

我想要保存到变量的新哈希数组:

$VAR2 = [
      {
        'Color' => 'green',
        '2nd Color' => 'blue',
        '3rd Color' => 'yellow',
        'toy' => 'truck',
        'toy_type' => 'ford',
        'kind' => '4door',
        'Stage' => 'Production',
        'Step' => 'Platform',
        'Datetime' => '2012/06/08 01:49:19'
      },
      {
        'Color' => 'red',
        '2nd Color' => 'blue',
        '3rd Color' => 'green',
        'toy' => 'truck',
        'toy_type' => 'chevy',
        'kind' => '4door',
        'Stage' => 'Production',
        'Step' => 'Platform',
        'Datetime' => '2012/06/08 01:52:14'
      },
      {
        'Color' => 'white',
        '2nd Color' => 'blue',
        '3rd Color' => 'yellow',
        'toy' => 'truck',
        'toy_type' => 'gmc',
        'kind' => '4door',
        'Stage' => 'Production',
        'Step' => 'Platform',
        'Datetime' => '2012/06/08 06:24:14'
      },

请注意我是如何只想存储最近的福特和最近的雪佛兰,但由于只有一个gmc,我也希望存储它。

我指的是perldsc(http://perldoc.perl.org/perldsc.html)文档,但它没有详细介绍。这甚至可能吗?

3 个答案:

答案 0 :(得分:3)

sub key { join ':', @{ $_[0] }{qw( toy kind Stage Step )} }

# Determine which records to keep.
my %latest;
for my $rec (@$recs) {
    my $key = key($rec);
    $latest{$key} = $rec->{Datetime}
       if !$latest{$key} || $latest{$key} lt $rec->{Datetime};
}        

# Filter out the others.
@$recs = grep { $latest{key($_)}{Datetime} eq $_->{Datetime} } @$recs;

上述方法保留原始订单。它还优雅地处理关系(保持两者)。

如果您不需要保留原始订单,则可以使用更简单的方法。不幸的是,它仅在一个平局的情况下保留一条记录,并且其性能也不会扩展[O(N log N)而不是O(N)]。

sub key { join ':', @{ $_[0] }{qw( toy kind Stage Step )} }

my %seen;
@$recs =
   grep !$seen{key($_)}++,
    sort { $b->{Datetime} cmp $a->{Datetime} }
     @$recs;

(如果您希望最终结果按升序reverse排序,请在grep前添加Datetime。)

答案 1 :(得分:0)

您是否考虑使用哈希散列?然后,您可以使用车辆的品牌作为外部哈希中的键,并且任何先前的条目都将被自动覆盖,因此您最终只会获得每个品牌的最新条目。

答案 2 :(得分:0)

您的数据似乎不具有代表性,首先是因为关键字段toykindStageStep在所有记录中都是相同的,并且因为数据没有像你说的那样排序(至少它没有按照我希望你的意思按日期/时间排序)。

此代码将返回数据中最早的唯一记录列表。根据您的数据,它只返回第四条记录,因为它的日期为2012/06/08 01:24:14,早于其他所有记录。

my %seen;

my @filtered = grep {
  not $seen{join '|', @$_{qw/ toy kind Stage Step /} }++
}
sort {
  $a->{Datetime} cmp $b->{Datetime}
} @data;