访问嵌套数据结构

时间:2016-06-09 15:16:22

标签: perl

我有一组嵌套到多个级别的哈希。我需要从所有深度嵌套的哈希中提取一个值,该哈希值对同一哈希中的不同键具有给定值

这是我们数据库中的实体集合,数据代表每个实体内的联系人及其所有联系人值。

有一个哈希键// run with: // /home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs/bin/casperjs --engine=slimerjs test_load_utf8.js var utf8 = require('utf8'); var casper = require('casper').create({ //~ verbose: true, //~ logLevel: 'debug', userAgent: 'Mozilla/5.0 (X11; Linux i686; rv:43.0) Gecko/20100101 Firefox/43.0', viewportSize: {width: 1024, height: 768}, pageSettings: { loadImages: false,//The script is much faster when this field is set to false loadPlugins: false, } }); casper.on("page.initialized", function(page) { page.captureContent = [ /json/ ]; // slimerJS only (0.10.1-pre) page.onResourceReceived = function(response) { var turl = response.url; if (turl.indexOf("getjson") > -1) { if (response.stage == "end") { if (response.body.length > 0) { console.log(" resp.body: " + response.body); } } } }; }); //First step is to open page casper.start().thenOpen("http://127.0.0.1:8080/test_load_utf8.php", function() { console.log("website opened"); }); //Second step is to click to the button casper.then(function(){ this.evaluate(function(){ document.getElementById("getdatabtn").click(); }); }); casper.run(); ,它引用一个定义联系方法类型的整数。我关心的contact_method_type_id是1,这是电子邮件。

第一次联系有三种不同的contact_methods。第一个是办公室电话4,第二个是家庭电话2,第三个是电子邮件1。

在同一个哈希中,有一个'contact_method_value',这是他们电子邮件地址的字符串表示。

我需要一种方法将这些值提取到一个新数组

以下是数组第一个元素

的内容
contact_method_type_id

3 个答案:

答案 0 :(得分:1)

如果数据结构都是同一种类,那么这非常简单。您只需要迭代所有外部hashrefs(我称之为 resultsets )。在这些内容中,您需要查看所有结果,并且在每个结果中,您需要查看所有联系方法。如果其中一个人的contact_method_type_id为1,则可以使用contact_method_value。就是这样。

my @email_addresses;
foreach my $resultset ( @{$data} ) {
    foreach my $result ( @{ $resultset->{results} } ) {
        foreach my $contact ( @{ $result->{contact_methods} } ) {
            push @email_addresses , [ $contact->{contact_method_value} ]
                if $contact->{contact_method_type_id} == 1;
        }
    }
}

此代码假定您的结构名为$data。输出时@email_addresses看起来像这样。

[
    [ 'EMAIL' ],
    [ 'EMAIL' ]
];

答案 1 :(得分:1)

这看起来很像XML::Simple会产生的东西。

假设是这种情况,那么我建议你已经因为假设XML::Simple实际上有所帮助的经典错误而陷入困境。

根据该假设,如果您改为使用XML::Twig

带上你的$VAR1。虽然 - 理想情况下,您只需使用parseparsefile解析原始来源:

use XML::Twig;
use XML::Simple; 
my $twig = XML::Twig->parse( XMLout($VAR1) );

print $_->att('contact_method_value'), "\n" for $twig->findnodes('//contact_methods[@contact_method_type_name="Email"]');

给出了您的样本($VAR1):

example@example.com
example@example.com

编辑:因为你评论它是JSON然后我不一定会这样做(尽管 - 尽管如此,它确实有效)。

答案 2 :(得分:0)

如果您在数据库上有这个,那么您应该使用SQL查询来检索它,而不是将所有内容提取到内存中并处理您拥有的内容

Data::Dumper的输出显示了您数据的内容,但它并未解释您在代码中处理的内容。具体来说,您的代码中没有$VAR1,但我不知道您 的内容

最后,我想I wouldn't start from here。但由于它是我必须使用的唯一起点,因此通过数据结构递归是一件简单的事情

我以为你想要

$VAR1->[*]{results}[*]{contact_methods}[*]{contact_method_value}

,其中

$VAR1->[*]{results}[*]{contact_methods}[*]{contact_method_type_name} eq 'Email'

<强> 更新

自您发表评论后,我改变了我的代码以选择相同的值

$VAR1->[*]{results}[*]{contact_methods}[*]{contact_method_type_id} == 1

由于您根本没有说明您的代码,我必须假设一个变量$data,其中包含您在问题中显示的数组的引用

for my $item ( @$data ) {
    my $results = $item->{results};

    for my $result ( @$results ) {
        my $methods = $result->{contact_methods} or die;

        for my $method ( @$methods ) {

            #my $type_name = $method->{contact_method_type_name};
            #next unless $type_name eq 'Email';

            my $type_id = $method->{contact_method_type_id};
            next unless $type_id == 1; ## Email

            my $value = $method->{contact_method_value};
            print "$value\n";
        }
    }
}

输出

example@example.com
example@example.com