gpt4 book ai didi

perl - 帮助遍历/排序复杂的 Perl 数据结构(HoH with AoH fun)

转载 作者:行者123 更新时间:2023-12-01 08:39:23 24 4
gpt4 key购买 nike

我已经用头撞墙了几个小时了。

我有一个看起来像这样的数据结构(来自“Data::Dumper”的输出)。这是我自己的错,我在解析一些输入时创建了数据结构。

print Dumper $data;

___OUTPUT___
$VAR = { 'NAME' => {
'id' => '1234',
'total' => 192,
'results' => {
'APPLE' => 48 ,
'KUMQUAT' => 61 ,
'ORANGE' => 33 ,
}
}

}
  • 有数千个“NAME”键。
  • 只有一个“id”和一个“total”。
  • “结果”哈希中可能有一个或多个键/值对。

我想打印一个逗号分隔的列表,首先按“total”排序,然后按“results”数组中每个散列的值排序。

以下代码用于从已存储的数据结构中打印出 CSV。

use strict;
use warnings;
# [...lots of other stuff...]

open (my $fh, >out.csv);
print $fh "Name, ID, Label, Count, Total\n";

foreach ( sort { $data->{$b}->{total} <=> $data->{$a}->{total} }
keys %{$data} )
{
my $name = $_;
foreach (
sort {
$data->{$name}->{results}->{$a} <=> $data->{$name}->{results}
->{$b}
} values %{ $data->{$name}->{results} }
)
{

print $fh $name . ","
. $data->{$name}->{id} . "," . "'"
. $_ . ","
. $data->{$name}->{results}->{$_} . "," . "\n";
}
print $fh $name . ","
. $data->{$name}->{id} . "," . "," . ","
. $data->{$name}->{total} . "\n";
}

close($fh);

这很好,效果很好(除了提醒我为什么不再使用 Perl)。

示例输出如下:

Name, ID,  Label,   Count, Total
foo, 1234, ORANGE, 33,
foo, 1234, APPLE, 48,
foo, 1234, KUMQUAT, 61,
foo, 1234, , , 142
bar, 1101, BIKE, 20,
bar 1101, , , 20

但是!我注意到我遇到了关键冲突(在“结果”哈希中),由于我需要保留并报告所有数据,我决定尝试将“结果”更改为哈希数组...

print Dumper $data;

___OUTPUT___
$VAR = { 'NAME' => {
'id' => '1234',
'total' => 192,
'results' => [
{ 'APPLE' => 48 },
{ 'KUMQUAT' => 61 },
{ 'ORANGE' => 33 },
{ 'APPLE' => 50 },
]
}
}
  • 有数千个“NAME”键。
  • 只有一个“id”和一个“total”。
  • “结果”数组中可能有一个或多个哈希值。
  • “results”数组中的每个哈希都只有一个名称/值对。

不管有没有人读到这么远,我不得不说写下来是相当有治疗作用的,所以我会继续……;-)

对于新的数据结构,排序/打印代码有问题。

use strict;
use warnings;
# [...lots of other stuff...]

open (my $fh, >out.csv);
print $fh "Name, ID, Label, Count, Total\n";

foreach ( sort { $data->{$b}->{total} <=> $data->{$a}->{total} }
keys %{$data} )
{
my $name = $_;
foreach (
sort {
$data->{$name}->{results}->{$a} <=> $data->{$name}->{results}
->{$b}
} values %{ $data->{$name}->{results} }
)
{
# .... HELP ME FOR THE LOVE OF ALL THAT IS GOOD IN THE WORLD! ....
# I'm at the point now where my brain is starting to slowly dribble from my
# ears...
}
print $fh $name . ","
. $data->{$name}->{id} . "," . "," . ","
. $data->{$name}->{total} . "\n";
}

close($fh);

如果你已经读到这里,我向你致敬。如果你能帮忙,我为你鼓掌。

如果有人对数据结构的替代格式有任何建议,请告诉我! (如果您有兴趣......我正在使用“触发器”运算符来捕获源文件的 block ,然后我使用这些 block 逐行创建数据结构。我也调用外部计算某些东西的程序(没有 Perl 等价物)并存储结果。)

谢谢

最佳答案

好的,我只想说一次:结构复杂时总是使用对象

正如您所发现的,您的大脑会在尝试跟踪哈希数组的哈希数组时爆炸。这是创建对象结构的完美理由。如果你永远不会重复使用它也没关系。它使您的编程任务变得容易得多。

以下花了我大约 30 分钟来编写和调试。如果你使用它,你会为自己省去很多心痛和调试。

作为奖励,当您发现您的错误假设(嘿,每个人都这样做!)您的 RESULT 数组中有多个具有相同键的项目时,您只需修改几行即可轻松定位代码尝试将所有内容保持在一起的整个程序。

我使用了您的数据结构,但我将 RESULTS 设为一个数组,该数组包含一个包含两个项目(标签和数量)而不是哈希的数组。我本可以使用哈希,但是这样,我可以返回一个包含两个项目的数组。现在,我想起来,无论如何都没有理由这样做。

#! /usr/bin/env perl

use warnings;
use strict;
use feature qw(say);
use Data::Dumper;


my %hash;
my $obj;

$obj = structure->new();
$obj->Name("foo");
$obj->Total("foo", 142);
$obj->Id("foo", 1234);
$obj->Push(qw(foo ORANGE 33));
$obj->Push(qw(foo APPLE 48));
$obj->Push(qw(foo APPLE 50));
$obj->Push(qw(foo KUMQUAT 61));
$obj->SortResults("foo");

$obj->Name("bar");
$obj->Total("bar", 20);
$obj->Id("bar", 1100);
$obj->Push(qw(bar BIKE 20));
$obj->SortResults("bar");

say Dumper($obj);
exit 0;

########################################################################
package structure;

use Data::Dumper;

#
# New Structure containing all data
#
sub new {
my $class = shift;

my $self = {};

bless $self, $class;
return $self;
}

#
# Either adds a new name object or returns name object;
#
sub Name {
my $self = shift;
my $name = shift;

if (not defined $self->{$name}) {
$self->{$name}->{ID} = undef;
$self->{$name}->{TOTAL} = undef;
$self->{$name}->{RESULTS} = [];
}
return $self->{$name};
}

#
# Returns a list of Names
#
sub NameList {
my $self = shift;

return keys %{$self};
}
#
# Either returns the id or sets $name's id
#
sub Id {
my $self = shift;
my $name = shift;
my $id = shift;

my $nameObj = $self->Name($name);
if (defined $id) {
$nameObj->{ID} = $id;
}
return $nameObj->{ID};
}

#
# Either returns the total for $name or sets $name's total
#
sub Total {
my $self = shift;
my $name = shift;
my $total = shift;

my $nameObj = $self->Name($name);
if (defined $total) {
$nameObj->{TOTAL} = $total;
}
return $nameObj->{TOTAL};
}

#
# Pushes new product and amount on $name's result list
#
sub Push {
my $self = shift;
my $name = shift;
my $product = shift;
my $amount = shift;

my $nameObj = $self->Name($name);
my @array = ("$name", "$amount");
push @{$nameObj->{RESULTS}}, \@array;
return @array;
}

#
# Pops product and amount on $name's result list
#
sub Pop {
my $self = shift;
my $name = shift;

my $nameObj = $self->Name($name);
my $arrayRef = pop @{$nameObj->{RESULTS}};
return @{$arrayRef};
}

sub SortResults {
my $self = shift;
my $name = shift;

my $nameObj = $self->Name($name);
my @results = @{$nameObj->{RESULTS}};
my @sortedResults = sort {$a->[1] <=> $b->[1]} @results;
my $nameObj->{RESULTS} = \@sortedResults;
return @sortedResults;
}

$obj->SortResults 将对结果进行就地排序,但无论如何您都可以使用它将结果作为排序列表检索。要按总计对项目进行排序,您可以使用:

my @sortedItems = sort {$obj->Total($a) <=> $obj->Total($b)} $obj->NameList();

简而言之,您可以节省自己的时间和清洁女工清理的烂摊子。 (爆炸的大脑很难从墙壁和天花板上擦掉)。

我从经验中了解到,每当您开始谈论包含指向其他散列的数组的散列的散列时,就该创建一个对象来处理困惑了。为这些类型的一次性工作创建对象似乎需要更长的时间,但根据我的经验,您通常可以在 30 分钟内大量制作所需内容并进行测试,这样可以节省您日后数小时的挫败感。

关于perl - 帮助遍历/排序复杂的 Perl 数据结构(HoH with AoH fun),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5873227/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com