【问题标题】:Efficient way to convert all array-value(s) to the correct data-type将所有数组值转换为正确数据类型的有效方法
【发布时间】:2021-12-14 04:15:36
【问题描述】:

如果我有一个每个值都是字符串的简单数组,我如何能够将每个值转换为正确的数据类型?示例:

$array = array(
    "stringExample" => "string", 
    "floatExample" => "1.24", 
    "intExample" => "1", 
    "boolExample" => "TRUE"
);

显然,float、integer 和 boolean 都是字符串,因为这就是它们被放入数组的方式。但我希望浮点数是一个实际的浮点数,整数是一个实际的整数等等。对于小型或固定数据集,我可以简单地将它们一一转换,但是在处理大量数据和/或动态数据时,这是不切实际的。应该是:

$array = array(
    "stringExample" => "string", 
    "floatExample" => 1.24, 
    "intExample" => 1, 
    "boolExample" => true
);

我能想到的唯一其他方法是创建一个循环来检查每个值以查看它是浮点数、布尔值还是其他值,但我觉得这样效率很低。也因为只有当值只是某种数据类型时才应该转换它。如果字符串是:"That's true",它应该是一个字符串,但如果它只是"true",它应该是一个布尔值。例如,1 也会使它变得复杂,因为这可以解释为布尔值和整数。但就我而言,这应该只是一个整数而不是布尔值。

有人有有效的方法来实现这一目标吗?一开始就这样做是明智的吗?也许某种数组过滤器?任何帮助表示赞赏!

【问题讨论】:

  • 老实说,现在的计算机非常快,我会从for 循环开始并一一转换。在您真正开始注意到性能问题之前,我不会担心它效率低下。如果您知道每个键应该是什么类型,则尤其如此。比如,floatExample 会提前知道是浮点数,还是需要测试每个值来猜测它应该是什么类型?如果是前者,而且你知道每个键对应的类型,我就循环遍历它,不用担心。
  • @404NotFound 我猜你是对的!这些值确实是提前知道的,所以这将是一个简单的转换案例。这确实是微秒的工作,但我想我记得有某种过滤器可以自动将值转换为正确的数据类型,但很可能我记错了。但是在非静态键值的情况下,你认为我应该如何处理呢?
  • 我不确定是否有任何过滤器会自动转换值,超出 PHP 的类型推断,但这并没有真正改变类型。我不确定如何处理非静态键值,但我的首先想到会使用filter_varctype_digitis_int/is_numeric 的组合/is_string/etc 并循环遍历值。我可能会从简单的类型变为复杂的类型,检查 bool、int、float、string 等,希望能减少你没有转换为最合适类型的机会。
  • 既然你说你知道他们正在使用的数据类型,为什么不在需要的时候强制转换它们呢?即:(int) $array['intExample']
  • @404NotFound filter_var 是一个非常聪明的主意。我创建了一个 foreach 循环聊天,使用 FILTER_VALIDATE_INTFILTER_VALIDATE_FLOATFILTER_VALIDATE_BOOL 检查每个值,它就像一个魅力。我并没有真正意识到我需要的只是这 3 种数据类型。

标签: php arrays type-conversion


【解决方案1】:

有一个技巧是使用带有JSON_NUMERIC_CHECK 标志的json_encode 函数,然后将其解码回来。但这会影响所有看起来像数字的字符串,因此值为 "TRUE" 的字符串将保持为字符串。

var_dump(json_decode(json_encode($array, JSON_NUMERIC_CHECK), true));
array(4) {
  ["stringExample"]=>
  string(6) "string"
  ["floatExample"]=>
  float(1.24)
  ["intExample"]=>
  int(1)
  ["boolExample"]=>
  string(4) "TRUE"
}

因此,您必须使用 filter_var 函数检查值来遍历数组:

array_walk_recursive($array, function(&$item){
    $filters = [FILTER_VALIDATE_INT, FILTER_VALIDATE_FLOAT, FILTER_VALIDATE_BOOLEAN];
    foreach($filters as $filter) {
        if (is_string($item)) {
            $item = filter_var($item, $filter, FILTER_NULL_ON_FAILURE) ?? $item;
            if (!is_string($item)) break;
        }
    }
});

demo

或者试试这个:

array_walk_recursive($array, function(&$item){
    $item = json_decode(
        json_encode($item, JSON_PRESERVE_ZERO_FRACTION | JSON_NUMERIC_CHECK)
    );
    if (is_string($item)) {
        $item = filter_var($item, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) ?? $item;
    }
});

var_dump($array);

demo

前导零的整数的结果存在差异。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 2023-04-01
    • 2023-03-07
    • 2022-12-07
    • 2019-03-08
    • 2022-11-16
    • 1970-01-01
    相关资源
    最近更新 更多