尝试更新旧的Perl代码时,不是ARRAY参考。 Hash to Array问题?

时间:2016-05-23 07:06:15

标签: arrays perl parsing hashtable

我正在尝试将过时的perl插件更新为Google的新API(他们更改了搜索调用)。我是Perl的新手,所以我不确定如何正确更新代码。我很确定我在尝试读取哈希时应该是一个数组吗?

数据结构转储:

$VAR1 = {
          'station_hits' => bless( do{\(my $o = 1726698624)}, 'Inline::Python::Object' ),
          'album_hits' => bless( do{\(my $o = 1726698288)}, 'Inline::Python::Object' ),
          'artist_hits' => bless( do{\(my $o = 1726698336)}, 'Inline::Python::Object' ),
          'situation_hits' => bless( do{\(my $o = 1726698384)}, 'Inline::Python::Object' ),
          'song_hits' => bless( do{\(my $o = 1726698432)}, 'Inline::Python::Object' ),
          'playlist_hits' => bless( do{\(my $o = 1726698480)}, 'Inline::Python::Object' ),
          'video_hits' => bless( do{\(my $o = 1726698528)}, 'Inline::Python::Object' )
        };

代码块:

# Search All Access
sub search {
        my $query = shift;

        return unless $prefs->get('all_access_enabled');

        my $uri = 'googlemusic:search:' . $query;

        if (my $result = $cache->get($uri)) {
                return $result;
        }

        my $googleResult;
        my $result = {
                tracks => [],
                albums => [],
                artists => [],
        };

        eval {
                $googleResult = $googleapi->search($query, $prefs->get('max_search_items'));
        };

        if ($@) {
                $log->error("Not able to search All Access for \"$query\": $@");
                return;
        }
        #My Attempt
        for my $hit (%@{$googleResult->{song_hits}}) {
                push @{$result->{tracks}}, to_slim_track($hit->{track});
        }
        #How it was originally
        for my $hit (@{$googleResult->{album_hits}}) {
                push @{$result->{albums}}, album_to_slim_album($hit->{album});
        }

我只在更改名称后收到此错误:

不是[LINE#]

的ARRAY参考

search_all_access 更改为搜索

有问题的一行:

for my $hit (@{$googleResult->{song_hits}}) {

我尝试过研究,在前面添加了一个%,但现在我在下一行收到错误。

'newlist'对象在[LINE#+ 1]

中没有属性'track'
 push @{$result->{tracks}}, to_slim_track($hit->{track});

编辑: 在解释了如何引用哈希应该如何工作之后进行更改后,我得到了这个:

 [16-05-23 10:22:36.7283] Slim::Networking::IO::Select::__ANON__ (131) Error: Select task failed calling Slim::Web::HTTP::processHTTP: Can't locate object method "FIRSTKEY" via package "Inline::Python::Object::Data" at /usr/lib/arm-linux-gnueabihf/perl/5.20/Data/Dumper.pm line 224.
; fh=Slim::Web::HTTP::ClientConn=GLOB(0x1007a188)

我不确定他们的代码中是否存在错误,或者Google是否在此最新错误后以不同的结构返回API数据。

3 个答案:

答案 0 :(得分:2)

这些对象似乎被抽象掉了。您可以阅读Inline::Python文档,但其中没有任何内容。然而,在code for the Inline::Python::Object中,有一个提示。

两行下来,有这个(省略矿井)。

use overload '%{}' => \&__data__, # [...]

如果它与哈希取消引用一起使用an overload,我们可以肯定它会在这种情况下返回哈希引用。

现在我们需要做的就是修复你引入的语法错误。你做了%@{},这是无效的语法。您需要@{}

,而不是数组deref %{}
for my $hit (%{ $googleResult->{song_hits} }) {
        push @{$result->{tracks}}, to_slim_track($hit->{track});
}

但是因为Perl中的哈希本质上是列表,所以现在将迭代键和值。这几乎不是一个好主意。相反,你应该iterate over the keys,然后使用它。或者更有可能的是,您感兴趣的每一个中只有一个密钥。如果有API描述,我建议您检查一下。这可能会有所帮助。

如果没有,Dumper就像这样。

print Dumper \%{ $googleResult->{song_hits} };

首先取消引用它,确保调用重载。由于Data :: Dumper并不将列表理解为数据结构,因此您将向其传递对返回的哈希的引用,因此您将获得$VAR1={}而不是$VAR1='foo'; $VAR2='bar',依此类推。

答案 1 :(得分:1)

如果您使用Data :: Dumper打印出这些数据结构,您很快就会看到它们的形式。然后您就不必猜测了。另外,不要将面向对象的调用样式误认为是散列访问。 ,它们是相同的,因为这就是Perl5对象的制作方式。

use data::dumper;
print "variable is :" + Dumper(@variable)

答案 2 :(得分:1)

我看不到预期的“更新”是什么,需要改变什么。但这里有一些评论。

首先:语法无效 - 不能有%@{...}。您可以取消引用对哈希,%{$hashref}或数组@{$arrayref}(或标量,$$scalarref)的引用。

您的数据结构很有趣。首先,它是一个哈希引用。 (或者,更确切地说,匿名哈希。)您可以完全取消引用它以创建哈希,或者可以为特定键提取值

my $href = { 'k1' => 'val1', 'k2' => 'val2' };
my $value_of_k1_key = $href->{'k1'};            # will be == val1

接下来,代码中的'value'正式成为一个对象。 bless函数将对数据结构(通常是hashref)的引用与类相关联,使其成为该类的对象(它返回)。

所以你真的有

$href = { 'station_hits' => $object, ... }

查询(任何)键后,您将返回该对象。

$object = $googleResult->{song_hits}

根据“#How the original ”下面显示的代码(我假设它有效),对象的数据结构是对数组的引用,而不是哈希,因为它取消引用数组。没关系。奇怪的是,它直接取消引用它,寻找其数据/属性。在一些其他语言的术语中,它正在访问(大概)私人成员。在Perl中,这是合法的并且将检索一个值但通常被认为是坏的,就像它被禁止一样。