【问题标题】:Iterating through a array of hashes in a hash that has multiple indexes遍历具有多个索引的哈希中的哈希数组
【发布时间】:2015-08-26 13:56:05
【问题描述】:

我目前正在编写一个 perl 脚本,其中包含一些哈希值: (不要把这当成代码行,只是为了展示/解释)

$details{tester_name} is "UFLEX-06"
$details{op_sys} is "Windows"
$details{igxl_vn} is "8.00.01_uflx (P7)"
$details{slot} -> see below for details
$details{board_name} -> see below for details

现在在 $details{slot} 我有多个索引,每个索引都包含一个值。

$details{slot} [0] has "2"
$details{slot} [1] has "5"

等等。 $details{slot} 的索引数量与 $details{board_name} 相同。

现在我想遍历这个但根据$details{slot}

到目前为止,我所做的仅迭代 %details

foreach my $key(keys %details)
{
    print {$fh} "INSERT INTO TesterDeviceMatrix.TBL_TESTER_INFO"
    ."(tester_name, operating_system , version, board_name , config , date_modified ) "
    ."VALUES ('$details{tester_name}', '$details{op_sys}', '$details{board_name}', "
    ."'$details{igxl_vn}', '$details{slot}', '$timestamp');\n";
}

但我想做的是类似

foreach my $key(keys %details{slot}) -> or %details{board_name}
{
    print {$fh} "INSERT INTO TesterDeviceMatrix.TBL_TESTER_INFO"
    ."(tester_name, operating_system , version, board_name , config , date_modified ) "
    ."VALUES ('$details{tester_name}', '$details{op_sys}', '$details{board_name}', "
    ."'$details{igxl_vn}', '$details{slot}', '$timestamp');\n";
}

我知道这是错误的,但这只是为了表明我的想法。

我现在得到的输出是:

INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'VirtualDSPBrd', '8.00.01_uflx (P7)', '66.0', '2015-06-11 11:15:33');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'VirtualDSPBrd', '8.00.01_uflx (P7)', '66.0', '2015-06-11 11:15:33');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'VirtualDSPBrd', '8.00.01_uflx (P7)', '66.0', '2015-06-11 11:15:33');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'VirtualDSPBrd', '8.00.01_uflx (P7)', '66.0', '2015-06-11 11:15:33');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'VirtualDSPBrd', '8.00.01_uflx (P7)', '66.0', '2015-06-11 11:15:33');

上面的输出有 5 行,因为有 5 个哈希值。但是我想要的是 8 行的值根据其索引,因为 $details{slot} 有 8 个索引,这意味着 $details{board_name} 也有 8 个索引。

我想要的输出的一个例子是(注意值差异和 8 行):

INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'abcBrd', '8.00.01_uflx (P7)', '2.0', '2015-06-11 11:15:33');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'VqwelDSPBrd', '8.00.01_uflx (P7)', '5.0', '2015-06-11 11:15:33');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'DiffDSPBrd', '8.00.01_uflx (P7)', '8.0', '2015-06-11 11:15:33');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', '123DSPBrd', '8.00.01_uflx (P7)', '26.0', '2015-06-11 11:15:33');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'V1r12alDSPBrd', '8.00.01_uflx (P7)', '56.0', '2015-06-11 11:15:33');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'VMamaBrd', '8.00.01_uflx (P7)', '52.0', '2015-06-11 11:15:33');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ONSPBrd', '8.00.01_uflx (P7)', '56.0', '2015-06-11 11:15:33');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'bankaiPBrd', '8.00.01_uflx (P7)', '66.0', '2015-06-11 11:15:33');

所以问题是我如何迭代然后根据哈希 $details{slot} 中有多少索引进行打印,$details{slot}$details{board_name} 将根据它们的索引打印?

我知道我必须在我拥有的当前循环中创建另一个 for 循环。但是,大多数解决方案都是针对只包含一个值的哈希,因此它不能满足我的需求。

编辑:

(注意:此转储仅显示最新的board_nameslot

{
    board_name => "Virtualabc"
    igxl_vn => "9.0.0_abc"
    op_sys => "Windows"
    slot => "66.0"
    tester_name => "UNFEK-02"
}

编辑 2:

按照@shivams 的建议,我已经编辑了我的脚本,将slotboard_name 声明为数组。

push @{ $details{slot} }, [$1];
push @{ $details{board_name} }, [$2];

现在,正如 Dmitry 的回答(第一部分)所建议的那样,我只得到了对数组的引用。这是输出:

INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [0]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [0]', '2015-06-11 15:18:37');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [1]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [1]', '2015-06-11 15:18:37');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [2]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [2]', '2015-06-11 15:18:37');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [3]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [3]', '2015-06-11 15:18:37');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [4]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [4]', '2015-06-11 15:18:37');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [5]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [5]', '2015-06-11 15:18:37');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [6]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [6]', '2015-06-11 15:18:37');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [7]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [7]', '2015-06-11 15:18:37');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [8]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [8]', '2015-06-11 15:18:37');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [9]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [9]', '2015-06-11 15:18:37');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [10]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [10]', '2015-06-11 15:18:37');
INSERT INTO TBL_TESTER_INFO(tester_name, operating_system , version, board_name , config , date_modified ) VALUES ('UFLEX-06', 'Windows XP', 'ARRAY(0x1d2fb98) [11]', '8.00.01_uflx (P7)', 'ARRAY(0x1d40288) [11]', '2015-06-11 15:18:37');

我如何获得确切的值?

【问题讨论】:

    标签: arrays perl loops hash hashmap


    【解决方案1】:

    您实际上不需要遍历keys %details。我接受它,您已经根据 Extracting data from log file into Perl hash 的 Borodin 的建议构建了 %details 哈希。在这种情况下,您所拥有的实际上并不是一个哈希数组,而是一个包含两个列表的单个哈希 %details(以及其他一些标量值)。

    为了从中准备所需的一组插入语句,您应该只遍历%details 的子列表。应该直接访问%details 的标量字段:

    for (my $i = 0; $i < @{$details{slot}}; $i++) {
        print
            "INSERT INTO TesterDeviceMatrix.TBL_TESTER_INFO"
            ."(tester_name, operating_system , version, board_name , config , date_modified ) "
            ."VALUES ('$details{tester_name}', '$details{op_sys}', '$details{board_name}[$i]', "
            ."'$details{igxl_vn}', '$details{slot}[$i]', '$timestamp');\n";
    }
    

    Here 是说明上述内容的测试脚本。

    在编辑 2 之后更新:

    改变

    push @{ $details{slot} }, [$1];
    push @{ $details{board_name} }, [$2];
    

    push @{ $details{slot} }, $1;
    push @{ $details{board_name} }, $2;
    

    [$var](即带方括号的标量变量)推入数组将使用包含单个标量值的单元素子数组填充数组。这是因为[$var] 构造了对包含单个元素$var 的数组的引用。相反,您真正需要的只是推送标量值本身。

    附言

    考虑使用参数化查询而不是硬编码查询。

    【讨论】:

    • 啊,是的,我根据鲍罗丁的建议建立了它。这种使用for 的迭代是我想到的并且最接近的。我尝试了你的方法,但我收到一条错误消息:“在 exTester.pl 第 51 行使用“strict refs”时,不能使用字符串 (“66.0”) 作为 ARRAY ref。”其中第 51 行指向 for 语句。
    • 好吧,当需要数组引用时,您似乎有一个标量值。您能否发布您的%details 哈希转储(例如,请参阅ideone.com/ITGear 中的Dumper() 调用)?
    • 而不是$details{slot}[$i][0]。这是因为push @{ $details{slot} }, [$1]; 填充@{ $details{slot} } 的不是所需的标量,而是包含这些标量的单元素数组。我相信您可以将您的push @{ $details{slot} }, [$1]; 更改为push @{ $details{slot} }, $1;(注意,修改后的版本中没有方括号)。在这种情况下,您应该能够使用$details{slot}[$i] 而无需更改。
    • ideone.com/mqy17v 这是完整的程序,如果您需要查看它,还有转储。用你的答案试了一下,得到了Global symbol "@details_array" requires explicit package name at exTester.pl line 52. Execution of exTester.pl aborted due to compilation errors.
    • @details_array 现在超出范围,因为您使用的是普通哈希(为了清楚起见,您可能希望将问题标题更改为“遍历嵌套在哈希中的数组”之类的内容)。这里:ideone.com/eT8WPD 是在我的测试数据上运行良好的更新版本。我所做的唯一更改是从 push 中删除方括号(第 30 和 31 行)
    【解决方案2】:
    foreach my $key(keys %details) {
     if (ref($key)  eq 'ARRAY') {
       foreach $key2 (@$key) {
          PRINT STATEMENT
       }
     }
     else {
      PRINT STATEMENT
     }
    }
    

    这样,当哈希中有数组时,您的代码将通过内部foreach 循环在该数组上循环,如果没有,它将转到else。现在你想如何使用价值完全取决于你。

    【讨论】:

    • 嗯,我明白了,+1 但我的问题仍然存在。我必须打印$details{slot} 中的每个值,但现在我只得到最新的值。现在,如果我在里面添加 print 语句,它什么也不会显示。
    • 尝试只在屏幕上而不是在文件上打印值。这也为您提供了最新的价值。你也可以在你的哈希上使用Dumper 并给出输出。
    • 那还有没有像dump这样的方法?因为在屏幕上我使用了转储,它确实显示了键中的每个值。
    • 使用Data::Dumper。我只是想要那个哈希,所以我可以试试。
    • 从你显示的转储中slot 没有array 作为值,而是简单的string,在输出中你只会得到那个字符串。
    猜你喜欢
    • 2012-08-22
    • 2022-01-19
    • 2016-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    相关资源
    最近更新 更多