【问题标题】:perl+json getting size of an arrayperl+json 获取数组的大小
【发布时间】:2016-05-03 11:03:45
【问题描述】:

我正在用 perl 读取一个 json 文件,但在使用结果时遇到了问题。

我想知道 json 文件中有多少视图。 应该有2个

my $data = decode_json($json);
print Dumper($data);

my @tmp=$data->{'views'};
my $nviews=scalar @tmp;
print "nviews : $nviews\n";

给我

$VAR1 = {
    'views' => [
        {
            'key' => 0,
            'value' => {
                'ptr_wrapper' => {
                     'data' => {
                         'width'    => 776,
                         'height'   => 1024,
                         'id_view'  => 0,
                         'filename' => '000118800_15821618907.jpg',
                         'id_pose'  => 0,
                         'id_intrinsic' => 13,
                         'local_path' => '/'
                     },
                     'id' => 2147483649
                 }
             }
        },
        {
             'key'   => 1,
             'value' => {
                 'ptr_wrapper' => {
                      'data' => {
                          'id_pose'      => 1,
                          'id_intrinsic' => 11,
                          'filename'     =>  '000132800_22050281512.jpg',
                          'id_view'      => 1,
                          'local_path'   => '/',
                          'width'        => 850,
                          'height'       => 1024
                      },
                      'id' => 2147483650
                  }
             }
         }
    ]
};
nviews : 1

在此先感谢您的帮助。luc

【问题讨论】:

标签: json perl


【解决方案1】:
my $views = $data->{views};
my $nbViews = scalar @$views;

$data->{views} 是对数组的引用,而不是数组。存储引用,并在需要时取消引用。

或者:

my @views = @{$data->{views}};
my $nbViews = scalar @views;

正如Borodin 所指出的,请注意,此替代方法会生成原始数组的副本(可能会占用大量内存)。在某些情况下,这可能是您真正想要做的(如果您需要修改它同时保持原件不变,但请注意这不是深层副本),但最常见的是(特别是如果您只想计算项目或迭代它们),您可能不想这样做,而只是坚持保留 reference (如上面的第一个代码 sn-p 中)。

【讨论】:

  • my $nbViews = scalar @{$data->{views}} 那样不行吗?
  • @Borodin 点被采取。
  • @dev-null:scalar 是不必要的,所以如果我不需要在其他地方访问数组,我会选择my $nbViews = @{ $data->{views} },但实际上这不太可能
  • @jcaron:我认为您应该明确说明您的 Alternatively 会复制数组,这通常是不必要的,如果@$data 非常大,可能会造成破坏.如果您只需要数组中的元素计数,这当然不是什么事情
【解决方案2】:

当你写这篇文章时

my $data = decode_json($json);

my @tmp = $data->{'views'};

您正在创建一个带有单个元素 $tmp[0] 的 Perl 数组,该元素与 $data->{'views'}相同

你的$data->{'views'} 是正确的,所以你已经正确理解了如何访问你的$data 变量引用的散列的views 元素,并且只要散列键views 看起来像一个Perl标识符,你可以忘记它周围的引号

但是 Perl 哈希和数组的值始终是标量,因此如果您需要访问数组,则必须取消引用它们,这同样适用于您需要访问的任何子结构

如果您正在处理复杂的数据结构,通常最好保留一个临时标量变量来跟踪您在结构中的位置。例如,我会写

my $views = $data->{views};

现在我有一个简单的 数组引用 来编写代码。我可以用@$views 将它取消引用到一个数组,我可以用$views->[0] 等访问它的元素。

这是对您自己的代码的重写,它符合我的描述。我还使用Data::Dump 重新格式化您显示的数据。它通常比Data::Dumper 的输出更简洁易读,但它不是核心模块,因此您可能需要安装它

我将$value->{ptr_wrapper} 作为词法变量$wrapper 提取出来,然后将$wrapper->{data} 作为词法变量$data 提取出来。其余的代码变得如此简单,否则我可能会写类似

的东西
say $data->{views}[0]{value}{ptr_wrapper}{data}{filename}


use strict;
use warnings 'all';
use feature 'say';

my $data = {
  views => [
    {
      key => 0,
      value => {
        ptr_wrapper => {
          data => {
            filename     => "000118800_15821618907.jpg",
            height       => 1024,
            id_intrinsic => 13,
            id_pose      => 0,
            id_view      => 0,
            local_path   => "/",
            width        => 776,
          },
          id => 2147483649,
        },
      },
    },
    {
      key => 1,
      value => {
        ptr_wrapper => {
          data => {
            filename     => "000132800_22050281512.jpg",
            height       => 1024,
            id_intrinsic => 11,
            id_pose      => 1,
            id_view      => 1,
            local_path   => "/",
            width        => 850,
          },
          id => 2147483650,
        },
      },
    },
  ],
};

my $views = $data->{views};
my $nviews = scalar @$views;

print "nviews : $nviews\n\n";

for my $view ( @$views ) {

    my $key     = $view->{key};
    my $value   = $view->{value};
    my $wrapper = $value->{ptr_wrapper};
    my $data    = $wrapper->{data};

    say "key      = $key";
    say "ID       = $wrapper->{id}";
    say "filename = $data->{filename}";
    say "height   = $data->{height}";
    say "width    = $data->{width}";
    print "\n";
}

输出

nviews : 2

key      = 0
ID       = 2147483649
filename = 000118800_15821618907.jpg
height   = 1024
width    = 776

key      = 1
ID       = 2147483650
filename = 000132800_22050281512.jpg
height   = 1024
width    = 850

【讨论】:

  • 完美。请注意,我不会使用我的 $data = $wrapper->{data};因为它会覆盖原始的 $data,我以后需要它。
  • @lulutreizequinze:它不会“覆盖”原始的$data。它引入了一个新的$data,它在封闭块的末尾消失——for 循环。之后,旧的$data 及其原始值可以再次访问。您不应该在循环内需要$data 的最外层值——这就是 scoping 的要点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 2020-07-24
  • 2016-05-13
  • 1970-01-01
  • 2015-11-04
  • 2022-07-22
相关资源
最近更新 更多