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,是否会收到任何警告;使用警告?++。我认为这是有原因的,但却忽略了思考原因可能是什么。