【问题标题】:apply different functions to each element of a Perl data structure对 Perl 数据结构的每个元素应用不同的函数
【发布时间】:2012-04-03 02:22:30
【问题描述】:

给定一个任意嵌套的数据结构,我如何创建一个新的数据结构,以便通过根据元素的类型对所有元素应用函数来标准化其中的所有元素.例如,我可能有

$data = {
    name => 'some one',
    date => '2010-10-10 12:23:45',
    sale => [34, 22, 65],
    cust => {
        name => 'Jimmy',
        addr => '1 Foobar Way',
        amnt => 452.024,
        item => ['books', 'pens', 'post-it notes']
    }
}

我想将所有文本值转换为大写,将所有日期转换为 UTC 日期时间,求所有整数的平方,将所有实数四舍五入并加 1,依此类推。因此,实际上,我想根据元素的类型对每个元素应用不同的函数。

实际上,数据可能通过数据库查询到达,在这种情况下它们已经是 Perl 数据结构,或者它们可能以 JSON 对象的形式开始存在,在这种情况下,我可以使用 JSON::from_json 将其转换为 Perl数据结构。思路是根据值类型标准化数据结构中的所有值,然后再将Perl数据结构作为JSON对象吐回来。

我阅读了the answers to executing a function on every element of a data structure 并认为 Data::Rmap 可能会解决问题,但不知道如何解决。 似乎 Rmap 也适用于所有 ,而不仅仅是

【问题讨论】:

    标签: json perl


    【解决方案1】:

    你提到的Data::Rmap简直太简单了。

    use Data::Rmap qw( rmap );
    rmap { $_ = transform($_); } $data;
    

    关于cmets中的问题:

    use Data::Rmap   qw( rmap );
    use Scalar::Util qw( looks_like_number );
    
    # Transforms $_ in place.
    sub transform {
       if (looks_like_number($_)) {
          if (...) {
             $_ *= 2;
          }
    
          $_ = 0+$_;  # Makes it look like a number to JSON::XS
       } else {
          ...
       }
    }
    
    &rmap(\&transform, $data);
    

    【讨论】:

    • 是的,它几乎可以工作。它似乎引用了所有数字,将它们视为字符串。所以字符串转换工作正常,但数字不受影响。给一个像if ($data =~ /\d+/) { return $data * 2; }这样的简单变换,我得到的是'34'而不是68
    • @punkish,不, 将它们视为字符串。匹配运算符匹配一个字符串。
    • 嗯...我不知道。那么,如何确保数字被视为数字而不是强制转换为字符串,而字符串仍然是字符串?我想通过34(将其转换为68)或35.03(将其转换为36)做正确的事) 同时留下 '34''35.03'
    • @punkish,适当地使用$_ = 0+$_; 就可以了。
    猜你喜欢
    • 2010-09-27
    • 2019-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多