Perl,检查空键值的各种类型的哈希,json

时间:2017-04-26 13:32:31

标签: json perl hash

我现在正在为我的功能实现某种模拟。我在这里有一点问题。根据情况,我可以获得不同类型的json以及它的不同类型的哈希。它可以是具有空值的空值的简单哈希,也可以是具有空值或非空值的哈希数组的哈希值。

my %ch1 = (
    "a" => "",
    "b" => "",
    "c" => ""
);

my %ch2 = (
    "tab" => [
        {   
            "a" => 11,
            "b" => 22,
            "c" => 33
        },
        {
            "a" => 44,
            "b" => 55,
            "c" => 66
        }
    ]
);

我需要创建一个函数来检查两种类型的哈希值,计算空值并与哈希键的数量进行比较。

这种方法适用于第一个哈希,但我不知道如何使它适用于没有硬编码的两个哈希。

my $tck = 0;
for (keys %ch1){
    if ($ch1{$_} eq ""){
        print "'$ch1{$_}'\n";
        $tck++;
    }
}
if ($tck == scalar keys %ch1){
    # do something
}

有什么建议吗?

3 个答案:

答案 0 :(得分:3)

您可以使用Data::Visitor::Callback来执行此操作。只要数据结构中没有其他包含空字符串的内容,它就是一个非常简单的实现。

模块访问数据结构中的每个项目,并在这些项目上调用用户定义的回调。它将为那些参考中的每个参考和每个值做到这一点。

use strict;
use warnings;
use Data::Visitor::Callback;

my %ch1 = (
    "a" => "",
    "b" => "",
    "c" => ""
);

my $empty_strings;
my $v = Data::Visitor::Callback->new(
    value => sub {
        ++$empty_strings if $_ eq q{}; # q{} is like '' but easier to read
    },
);

$v->visit( \%ch1 );
print $empty_strings;

这将输出3,因为输入哈希中有三个空字符串。请注意,它需要哈希引用,而不是哈希本身。

您也可以传递更复杂的数据结构。布局并不重要。我在第二个例子中添加了一个空字符串,表明它可以正常工作。

use strict;
use warnings;
use Data::Visitor::Callback;

my $empty_strings;
my $v = Data::Visitor::Callback->new(
    value => sub {
        ++$empty_strings if $_ eq q{};
    },
);

my %ch2 = (
    "tab" => [
        {
            "a" => 11,
            "b" => 22,
            "c" => 33
        },
        {
            "a" => '',
            "b" => 55,
            "c" => 66
        }
    ]
);

$v->visit( \%ch2 );
print $empty_strings;

在这种情况下,输出为1

因为没有简单的方法来区分它所看到的值是键还是值,所以这个实现也会计算以下内容。所以它并不完美,但应该适用于您展示的数据类型。

my %fail = (
    ""  => "foo",        # one
    "b" => [ "", "" ],   # two, three
);

此数据结构将产生$empty_strings 3的数量。

答案 1 :(得分:0)

我不确定我是否正确理解了这个问题,但假设这些是您的程序需要能够处理的两种类型的数据结构,这里有一种方法可以解决它:

#!/usr/bin/env perl

use strict;
use warnings;

use List::MoreUtils qw( all none );

my %ch1 = (
    "a" => "",
    "b" => "",
    "c" => ""
);

my %ch2 = (
    "tab" => [
        {
            "a" => 11,
            "b" => 22,
            "c" => 33
        },
        {
            "a" => 44,
            "b" => 55,
            "c" => 66
        }
    ]
);

use YAML::XS;
for my $h ( \(%ch1, %ch2) ) {
    print Dump n_keys_empty_values( $h );
}

sub n_keys_empty_values {
    my $h = shift;

    if ( all { ref } values %$h ) {
        return [ map { my $v = $_; map count_empty_values( $_ ), @$v } values %$h ]
    }
    elsif ( none { ref } values %$h ){
        return [ count_empty_values( $h ) ];
    }
    else {
        die "Unexpected data structure\n";
    }
}

sub count_empty_values {
    my $h = shift;
    [ scalar keys %$h, scalar grep $_ eq '', values %$h ];
}

输出:

---
- - 3
  - 3
---
- - 3
  - 0
- - 3
  - 0

n_keys_empty_values的返回值是对数组引用数组的引用。外部数组的大小对应于传递的内部哈希的数量。 count_empty_values接受对散列的引用,并计算键数和空字符串值。

答案 2 :(得分:0)

以这种方式编写函数,它遍历参数列表。然后,您可以将单个散列\%ch1或散列@{$ch2{tab}}列表传递给函数。

#! /usr/bin/perl
use strict;
use warnings;

my %ch1 = (
    "a" => "",
    "b" => "",
    "c" => ""
);

my %ch2 = (
    "tab" => [
        {
            "a" => 11,
            "b" => 22,
            "c" => 33
        },
        {
            "a" => 44,
            "b" => 55,
            "c" => 66
        }
    ]
);

my %ch3 = (
    "tab" => [
        {
            "a" => '',
            "b" => '',
            "c" => ''
        },
        {
            "a" => '',
            "b" => '',
            "c" => ''
        }
    ]
);

sub fun
{
  for (@_) {
    my %ch = %{$_};
    my $tck = 0;
    for (keys %ch){
      if ($ch{$_} eq ""){
        print "'$ch{$_}'\n";
        $tck++;
      }
    }
    if ($tck == scalar keys %ch){
      print "do something\n";
    }
  }
}

fun (\%ch1);
fun (@{$ch2{tab}});
fun (@{$ch3{tab}});