Perl 有序散列-设置和访问键/值对
我想实现一个有序散列,其中每个键值对的值将是另一个嵌套的散列映射。我不能这样做。我没有收到任何错误,但没有打印任何内容Perl 有序散列-设置和访问键/值对,perl,data-structures,hash,associative-array,perl-data-structures,Perl,Data Structures,Hash,Associative Array,Perl Data Structures,我想实现一个有序散列,其中每个键值对的值将是另一个嵌套的散列映射。我不能这样做。我没有收到任何错误,但没有打印任何内容 use Hash::Ordered; use constant { lead_ID => 44671 , lag_ID => 11536 , start_time => time }; my $dict_lead=Hash::Ordered->new; my $dict_lag=Hash::Ordered->new; open(my $f1,"
use Hash::Ordered;
use constant { lead_ID => 44671 , lag_ID => 11536 , start_time => time };
my $dict_lead=Hash::Ordered->new;
my $dict_lag=Hash::Ordered->new;
open(my $f1,"<","tcs_07may_nse_fo") or die "cant open input file";
open(my $f2,">","bid_ask_".&lead_ID) or die "cant open output file";
open(my $f3,">","ema_data/bid_ask_".&lag_ID) or die "cant open output file";
while(my $line =<$f1>){
my @data=split(/,/,$line);
chomp(@data);
my ($tstamp, $instr) = (int($data[0]), $data[1]);
if($instr==&lead_ID){
$dict_lead->set($tstamp=>{"bid"=>$data[5],"ask"=>$data[6]});
}
if($instr==&lag_ID){
$dict_lag->set($tstamp=>{"bid"=>$data[5],"ask"=>$data[6]});
}
}
close $f1;
foreach my $key ($dict_lead->keys){
my $spread=$dict_lead{$key}{"ask"}-$dict_lead{$key}{"bid"};
%hash=$dict_lead->get($key);
print $key.",".$hash{"ask"}."\n";
print $f2 $key.",".$dict_lead{$key}{"bid"}.","
.$dict_lead{$key}{"ask"}.",".$spread."\n";
}
foreach my $key ($dict_lag->keys){
my $spread=$dict_lag{$key}{"ask"}-$dict_lag{$key}{"bid"};
print $f3 $key.",".$dict_lag{$key}{"bid"}.","
.$dict_lag{$key}{"ask"}.",".$spread."\n";
}
close $f2;
close $f3;
print "Ring destroyed in " , time() - &start_time , " seconds\n";
从输出的第一列开始,我意识到我能够在有序散列中插入密钥。但我不明白如何插入另一个散列作为这些键的值。另外,在遍历散列的键时,如何访问这些值
与文件句柄$f2
对应的文件中的输出为:
1430970394,,,0
1430970395,,,0
1430970396,,,0
1430970397,,,0
1430970398,,,0
1430970399,,,0
1430970400,,,0
对于使用构造的有序散列,散列是一个对象。这些对象具有属性(例如,索引;如果您检查
Hash::Ordered
对象,则该对象中不仅包含Hash元素),而且还提供了操作和访问其数据的方法。因此,您需要使用访问散列,就像您在这一行中所做的那样:
$dict_lead->set($tstamp=>{"bid"=>$data[5],"ask"=>$data[6]});
其中,您使用标量$tstamp
创建一个键,然后将其与一个匿名散列关联为它的值
但是,当您使用Hash::Ordered
对象时,您的脚本还使用了一个简单的数据结构(%Hash
),您在第一个foreach
循环中使用$dict\u lead->get($key)
填充该结构。在这种情况下,所有用于向散列添加键的常规技术、习惯用法和规则仍然适用。您不想重复将嵌套哈希从$dict_lead
哈希::Ordered
对象复制到%hash
这里,您要将嵌套哈希添加到%hash
并将其与唯一键关联
如果没有要测试的样本数据或要与之比较的预期输出的描述,很难确定,但您可能只需要更改:
%hash=$dict_lead->get($key);
例如:
$hash{$key} = $dict_lead->get($key);
要正确填充临时的%hash
。或者,由于每个键的值都是嵌套的匿名哈希,因此您可能希望尝试更改“print$key.”、“$hash{”ask“}.\n”代码>至:
print $key.",".$hash{$key}{"ask"}."\n"
还有其他方法可以将一个嵌套数据结构的一部分“深度”复制到另一个嵌套数据结构(请参见下面的Stackoverflow参考),您可能可以避免同时使用临时变量,但这些小的更改可能是您的情况所需的全部内容
通常,为了“插入另一个散列作为…键的值”,您需要使用引用或匿名散列构造函数({k=>“v”,…}
)。例如,添加一个键:
my %sample_hash ;
$sample_hash{"key_0"} = { bid => "1000000" , timestamp => 1435242285 };
dd %sample_hash ;
输出:
("key_0", { bid => 1000000, timestamp => 1435242285 })
(
"key_1",
{ bid => 1000000, timestamp => 1435242285 },
"key_0",
{ bid => 1400000, timestamp => 1435242395 },
"key_2",
{ bid => 2000000, timestamp => 1435244898 },
)
要将多个密钥从一个散列添加到另一个散列,请执行以下操作:
my %to_add = ( key_1 => { bid => "1500000" , timestamp => 1435242395 },
key_2 => { bid => "2000000" , timestamp => 1435244898 } );
for my $key ( keys %to_add ) {
$sample_hash{$key} = $to_add{$key}
}
dd %sample_hash ;
输出:
("key_0", { bid => 1000000, timestamp => 1435242285 })
(
"key_1",
{ bid => 1000000, timestamp => 1435242285 },
"key_0",
{ bid => 1400000, timestamp => 1435242395 },
"key_2",
{ bid => 2000000, timestamp => 1435244898 },
)
工具书类
- ++
首先,我不明白您为什么要使用一个模块来保持哈希有序。我假定您希望输出按时间戳字段排序,并且您从输入文件中读取的数据已经按此顺序排序,但是对普通散列的键进行排序并按顺序打印内容很简单,而不需要依赖预排序的传入数据
您已经阅读了一篇解释,解释了为什么您的代码不能正常运行。这就是我将如何编写一个希望能够正常运行的解决方案(尽管除了检查它是否编译之外,我还无法对它进行测试)
我选择使用两个元素的数组来包含每个时间戳的要价和要价,而不是散列。这将使代码运行速度略微加快,同时使其更简单、更易于阅读
还值得注意的是,我添加了use autodie
,这使perl能够自动检查IO操作的状态,如open
和chdir
,并消除手动编码这些检查所造成的混乱。我还为文件根目录的路径定义了一个常量,并使用chdir
在那里设置工作目录。这样就无需重复该部分路径,并减少了剩余文件路径字符串的长度
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use autodie;
use Hash::Ordered;
use constant DIR => '../tcs_nse_fo_merged';
use constant LEAD_ID => 44671;
use constant LAG_ID => 11536;
chdir DIR;
my $dict_lead = Hash::Ordered->new;
my $dict_lag = Hash::Ordered->new;
{
open my $fh, '<', 'tcs_07may_nse_fo';
while ( <$fh> ) {
chomp;
my @data = split /,/;
my $tstamp = int $data[0];
my $instr = $data[1];
if ( $instr == LEAD_ID ) {
$dict_lead->set( $tstamp => [ @data[5,6] ] );
}
elsif ( $instr == LAG_ID ) {
$dict_lag->set( $tstamp => [ @data[5,6] ] );
}
}
}
{
my $file = 'ema_data/bid_ask_' . LEAD_ID;
open my $out_fh, '>', $file;
for my $key ( $dict_lead->keys ) {
my $val = $dict_lead->get($key);
my ($ask, $bid) = @$val;
my $spread = $ask - $bid;
print join(',', $key, $ask), "\n";
print $out_fh join(',', $key, $bid, $ask, $spread), "\n";
}
}
{
my $file = 'ema_data/bid_ask_' . LAG_ID;
open my $out_fh, '>', $file;
for my $key ( $dict_lag->keys ) {
my $val = $dict_lead->get($key);
my ($ask, $bid) = @$val;
my $spread = $ask - $bid;
print $out_fh join(',', $key, $bid, $ask, $spread), "\n";
}
}
printf "Ring destroyed in %d seconds\n", time - $^T;
#/usr/bin/perl
严格使用;
使用警告;
使用5.010;
使用自动模具;
使用Hash::Ordered;
使用常量DIR=>'../tcs_nse_fo_merged';
使用常量LEAD_ID=>44671;
使用常数LAG_ID=>11536;
chdir-DIR;
my$dict_lead=Hash::Ordered->new;
my$dict_lag=Hash::Ordered->new;
{
打开我的$fh、、$文件;
对于我的$key($dict\u lead->key){
我的$val=$dict_lead->get($key);
我的($ask,$bid)=@$val;
我的$spread=$ask-$bid;
打印联接(“,”,$key,$ask),“\n”;
打印$out\u fh join(“,”,$key,$bid,$ask,$spread),“\n”;
}
}
{
my$file='ema\u data/bid\u ask\u'.LAG\u ID;
打开我的$out\u fh,“>”,$file;
对于我的$key($dict\u lag->keys){
我的$val=$dict_lead->get($key);
我的($ask,$bid)=@$val;
我的$spread=$ask-$bid;
打印$out\u fh join(“,”,$key,$bid,$ask,$spread),“\n”;
}
}
printf“戒指在%d秒内销毁\n”,时间-$^T;
如果添加使用strict,是否会收到任何警告;使用警告第一句话的代码>?++。我认为这是有原因的,但却忽略了思考原因可能是什么。