繁体   English   中英

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

[英]Perl, checking various types of hash for empty key values, json

我现在正在为我的函数实现某种模拟。 我在这里有一个小问题。 根据情况,我可以获取不同类型的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
}

有什么建议么?

您可以使用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

我不确定我是否正确理解了这个问题,但是假设这是程序需要处理的仅有的两种数据结构类型,这是对它们进行处理的一种方法:

#!/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引用哈希,并计算键的数目和值为空字符串的值的数目。

以这种方式编写函数,使其遍历参数列表。 然后,您可以将单个哈希\\%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}});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM