Perl 散列数组
在perl中,我有一个哈希数组 像 现在我需要在标题和作者相同的情况下累加数量。 在上面的title=1177和author='ABC'散列结构中,数量可以累加为一个,整个结构如下所示Perl 散列数组,perl,hash,Perl,Hash,在perl中,我有一个哈希数组 像 现在我需要在标题和作者相同的情况下累加数量。 在上面的title=1177和author='ABC'散列结构中,数量可以累加为一个,整个结构如下所示 0 HASH(0x98335e0) 'title' => 1177 'author' => 'ABC' 'quantity' => 0 1 HASH(0x98335e0) 'title' => 1127 'author' => 'DEF' '
0 HASH(0x98335e0)
'title' => 1177
'author' => 'ABC'
'quantity' => 0
1 HASH(0x98335e0)
'title' => 1127
'author' => 'DEF'
'quantity' => '5100'
2 HASH(0x832a9f0)
'title' => 1277
'author' => 'XYZ'
'quantity' => '1030'
我可以用什么样的最佳方式来进行这种积累,以使其得到优化?数组元素的数量可能非常大。我不介意在散列中添加一个额外的键来帮助相同的操作,但是我不想进行n次查找。恳请告知
my %sum;
for (@a) {
$sum{ $_->{author} }{ $_->{title} } += $_->{quantity};
}
my @accumulated;
foreach my $author (keys %sum) {
foreach my $title (keys %{ $sum{$author} }) {
push @accumulated => { title => $title,
author => $author,
quantity => $sum{$author}{$title},
};
}
}
不确定map
是否会让它看起来更好:
my @accumulated =
map {
my $author = $_;
map { author => $author,
title => $_,
quantity => $sum{$author}{$_},
},
keys %{ $sum{$author} };
}
keys %sum;
如果不需要N个查找,那么需要一个哈希函数——不过需要用该哈希函数存储它们。当您将它们放入列表(或数组)时,已经太晚了。你要么一直都很幸运,,要么就会有N次查找 或将它们插入下面的散列中。混合解决方案是将定位器存储为列表/数组中的项0
my $lot = get_lot_from_whatever();
my $tot = $list[0]{ $lot->{author} }{ $lot->{title} };
if ( $tot ) {
$tot->{quantity} += $lot->{quantity};
}
else {
push @list, $list[0]{ $lot->{author} }{ $lot->{title} } = $lot;
}
先前的 首先,我们将对其进行重新格式化以使其可读
[ { title => 1177, author => 'ABC', quantity => '-100' }
, { title => 1177, author => 'ABC', quantity => '100' }
, { title => 1127, author => 'DEF', quantity => '5100' }
, { title => 1277, author => 'XYZ', quantity => '1030' }
]
接下来,您需要分解问题。你想把大量的东西分组
按作者和标题。所以你需要这些东西来唯一地识别那些地段。
要重复,您需要一组名称来标识实体。因此,你
将需要一个按名称标识事物的哈希
因为我们有两件事,所以双哈希是一种很好的方法
my %hash;
foreach my $lot ( @list ) {
$hash{ $lot->{author} }{ $lot->{title} } += $lot->{quantity};
}
# consolidated by hash
要将其返回到列表中,我们需要分解级别
my @consol
= sort { $a->{author} cmp $b->{author} || $a->{title} cmp $b->{title} }
map {
my ( $a, $titles ) = @$_; # $_ is [ $a, {...} ]
map { +{ title => $_, author => $a, quantity => $titles->{$_} }
keys %$titles;
}
map { [ $_ => $hash{$_} ] } # group and freeze a pair
keys %hash
;
# consolidated in a list.
你拿回来了,我甚至帮你整理好了。当然你也可以
按出版商是什么来排序,数量递减
sort { $b->{quantity} <=> $a->{quantity}
|| $a->{author} cmp $b->{author}
|| $a->{title} cmp $b->{title}
}
sort{$b->{quantity}$a->{quantity}
||$a->{author}cmp$b->{author}
||$a->{title}cmp$b->{title}
}
我认为退一步考虑数据的来源是很重要的。如果数据来自数据库,则应编写SQL查询,以便为每个作者/标题组合提供一行,并在数量字段中显示总数量。如果您正在从文件中读取数据,那么您应该将其直接读取到散列中,或者在顺序重要时使用
一旦像您这样将数据放入一个hashref数组中,您就必须创建一个辅助数据结构并进行一系列查找,其成本可能会主导程序的运行时间(如果每天运行一次15分钟并不重要),并且您可能会遇到内存问题。“我不需要n次查找”,但是如果不访问数组的每个成员,就无法在整个数组中累积。请将和添加到您的阅读列表中。此示例只是想获得一些map/greplove@Daenyth通常是的,但在这种情况下看起来不太好。
sort { $b->{quantity} <=> $a->{quantity}
|| $a->{author} cmp $b->{author}
|| $a->{title} cmp $b->{title}
}