PHP数组Key强制类型转换实现原理解析

PHP是弱类型语言,就像JavaScript一样,在定义变量时,不需要强制指定变量的类型。同时,PHP又有着强大的数组功能,数组的Key即可以是普通的数字类型下标,也可以是字符串类型的Hash键值,那么,当一个数组的Key同时拥有字符串和数字时,会产生什么情况呢?

首先来看下面这样一段代码:

$arr = [
  "1" => "a",
  "01" => "b",
  1 => "aa",
  1.1 => "aaa",
  "0.1" => "bb",
];

var_dump($arr);

// array(3) {
//   [1] =>
//   string(3) "aaa"
//   '01' =>
//   string(1) "b"
//   '0.1' =>
//   string(2) "bb"
// }

咦?我们定义的"1"、1下标的值都变成了1.1的"aaa"了?

没错,PHP中的数组Key值只接受数字和字符串类型,当Key是字符串时,会强制转换为数字类型,遵守类型强制转换的规则。浮点数也是同样的道理,直接转换成了向下取整的整型。

那么"0.1"和"01"为什么还在?首先,"01"不是标准的十进制数值,无法转换成整型,所以"01"还是一个字符串下标,那"0.1"呢?它当然也不是一个标准的十进制数值。这里是违背了字符串转型数字的强制类型转换原则的,在变量的强制转换中,这两种字符串都会被转换为0,但在数组中则不会,这里会是一个坑,也是需要注意的地方。

在PHP官方文档中给出的Key值转换说明如下:

  • 包含有合法整型值的字符串会被转换为整型。例如键名 "8" 实际会被储存为 8。但是 "08" 则不会强制转换,因为其不是一个合法的十进制数值。
  • 浮点数也会被转换为整型,意味着其小数部分会被舍去。例如键名 8.7 实际会被储存为 8。
  • 布尔值也会被转换成整型。即键名 true 实际会被储存为 1 而键名 false 会被储存为 0。
  • Null 会被转换为空字符串,即键名 null 实际会被储存为 ""。
  • 数组和对象不能被用为键名。坚持这么做会导致警告:Illegal offset type。

接下来,是笔者曾经做过的一道面试题,和这个类型转换有着非常大的关系,代码如下:

a   = ['a'];
$a[2]  = 'b';
$a[]  = 'c';
$a['1'] = 'd';

// 以下循环的输出结果是?
foreach ($a as $v) {
	echo $v, ',';
}

// 以下循环的输出结果是?
for ($i = 0; $i < count($a); ++$i) {
	echo $a[$i], ' ,';
}

大家先不要运行,直接看代码看看能不能看出这两段代码的输出结果会是什么,然后运行一下,看看结果和你想像的是不是一样。

测试代码: https://github.com/zhangyue0503/dev-blog/blob/master/php/201910/source/关于PHP数组Key的强制转换.php

参考资料: https://www.php.net/manual/zh/language.types.array.php

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • PHP实现向关联数组指定的Key之前插入元素的方法

    本文实例讲述了PHP实现向关联数组指定的Key之前插入元素的方法.分享给大家供大家参考,具体如下: PHP 关联数组可以通过三种方式插入新元素: 1. $array[$insert_key] = $insert_value; 2. $array = array_merge($array, $insert_array); 3. $array = $array+$insert_array; 但是如果要在指定的键之前插入元素呢?下面的代码将 $data 插入关联数组 $array 的键名为 $key

  • PHP根据key删除数组中指定的元素

    php数组中元素的存在方式是以键值对的方式('key'=>'value'),有时候我们需要根据键删除数组中指定的某个元素. function bykey_reitem($arr, $key){ if(!array_key_exists($key, $arr)){ return $arr; } $keys = array_keys($arr); $index = array_search($key, $keys); if($index !== FALSE){ array_splice($arr,

  • php array_key_exists() 与 isset() 的区别

    php array_key_exists用于检查某个键名是否存在于数组中,而isset也可以用于检测数组中某个键名是否存在,那么二者有什么区别呢?本文章将为大家讲解array_key_exists() 与 isset() 使用中的一些区别 一个基本的区别是isset()可用于数组和变量,而array_key_exits()只能用于数组. 但是最主要的区别在于在设定的条件下的返回值. 现在我们来验证一下这个最主要的区别. array_key_exists() array_key_exists()

  • PHP使用自定义key实现对数据加密解密的方法

    本文实例讲述了PHP使用自定义key实现对数据加密解密的方法.分享给大家供大家参考,具体如下: 客户端和服务端通信时,有个场景很常见,通过一个id作为url参数来回传递.假设现在业务上只有这个id标识,那么需要稍微安全一点的通信,对这个id进行加密传输,到服务端再进行解密.这里需要一个服务端进行保密的key,利用这个key进行加密和解密. 加解密的方法如下:$str是需要加解密的字符串,$key是自己定义的一个key // 加密 function encryptStr($str, $key){

  • PHP array_key_exists检查键名或索引是否存在于数组中的实现方法

    array_key_exists() PHP array_key_exists() 函数用于检查给定的键名或索引是否存在于数组中,如果存在则返回 TRUE ,否则返回 FALSE . 语法: bool array_key_exists( mixed key, array search )参数 key 是给定的键名或索引,可以是任何能作为数组索引的值. array_key_exists() 函数也可用于对象. 例子: <?php $arr_a = array('id' => 1, 'name'

  • PHP 根据key 给二维数组分组

    我们经常拿到一个二维数组出来,会发现结果和自己想要的有些偏差,可能需要根据二维数组里的某个字段对数组分组. 先来看以下数组, Array ( [0] => Array ( [id] => 1 [wo_id] => 2 [evaluate_id] => 1 [type] => 分组1 [ctime] => 2016-12-02 11:39:34 ) [1] => Array ( [id] => 2 [wo_id] => 31 [evaluate_id]

  • php array_keys 返回数组的键名

    array_keys返回数组中部分的或所有的键名 说明 array array_keys ( array $array [, mixed $search_value [, bool $strict = false ]] ) array_keys() 返回 $array 数组中的数字或者字符串的键名. 如果指定了可选参数 search_value,则只返回该值的键名.否则 $array 数组中的所有键名都会被返回. 参数详解 参数 描述 array 必需.一个数组,包含了要返回的键. search

  • PHP实现二维数组根据key进行排序的方法

    本文实例讲述了PHP实现二维数组根据key进行排序的方法.分享给大家供大家参考,具体如下: 在PHP中内置了很多对数组进行处理的函数,有很多时候我们直接使用其内置函数就能达到我们的需求,得到我们所想要的结果:但是,有的时候我们却不能通过使用内置函数实现我们的要求,这就需要我们自己去编写算法来对自己的想法进行实现.下面就讲述一下如何实现二维数组根据key进行排序. 实现方法: <?php /** * ======================================= * Created

  • PHP数组Key强制类型转换实现原理解析

    PHP是弱类型语言,就像JavaScript一样,在定义变量时,不需要强制指定变量的类型.同时,PHP又有着强大的数组功能,数组的Key即可以是普通的数字类型下标,也可以是字符串类型的Hash键值,那么,当一个数组的Key同时拥有字符串和数字时,会产生什么情况呢? 首先来看下面这样一段代码: $arr = [ "1" => "a", "01" => "b", 1 => "aa", 1.1

  • PHP数组实际占用内存大小原理解析

    一般来说,PHP数组的内存利用率只有 1/10, 也就是说,一个在C语言里面100M 内存的数组,在PHP里面就要1G.下面我们可以粗略的估算PHP数组占用内存的大小,首先我们测试1000个元素的整数占用的内存: <?php echo memory_get_usage() , '<br>'; $start = memory_get_usage(); $a = Array(); for ($i=0; $i<1000; $i++) { $a[$i] = $i + $i; } $mid

  • Python max函数中key的用法及原理解析

    一.背景 起源于一个问题:怎样找到字符串中出现次数最多的字符 其实使用max函数就能很轻松的解决这个问题: 代码: str1 = "AAAaaa8888899sssss" print(max(str1, key=str1.count)) 结果:8 二.原理 max()函数用于获得给定的可迭代对象中的最大值. key是max()函数的一个参数,它辅助max函数找到最大元素.当max() 函数中有 key 参数时,求的是 value 的最大值,当没有 key 参数时,求的是 key 的最大

  • 解析C++中四种强制类型转换的区别详解

    C++的四种强制类型转换,所以C++不是类型安全的.分别为:static_cast , dynamic_cast , const_cast , reinterpret_cast为什么使用C风格的强制转换可以把想要的任何东西转换成合乎心意的类型.那为什么还需要一个新的C++类型的强制转换呢?新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换.C++中风格是static_cast<type>(content).C++风格的强制转换其他的好处是,它们能更清晰的表明它们要干

  • C语言基础隐式类型转换与强制类型转换示例解析

    目录 类型转换 隐式类型转换 强制类型转换 类型转换 数据有不同的类型,不同类型数据之间进行混合运算时必然涉及到类型的转换问题. 转换包括隐式类型转换和强制类型转换. 类型转换的原则:占用内存字节数少(值域小)的类型,向占用内存字节数多(值域大)的类型转换,以保证精度不降低. 隐式类型转换 隐式转换也称为自动转换,遵循一定的规则,由编译器自动完成. C的整型算数运算总是至少以缺省整型类型的精度来进行,为了获得这个精度,表达式中的字符和短整形操作数在使用之前都被转换成普通整型,这种转换为整型提升.

  • php foreach 参数强制类型转换的问题

    所以,为了防止这样的信息出现,我使用foreach的时候,都会把参数进行强制类型转换,形势如下: foreach((array)$arr as $key => $value); 这样做一直相安无事,就在前几天,突然出现了问题.我强制类型转换以后不能正常的调用object的方法了. 复制代码 代码如下: <?php class service implements Iterator{ function __construct($service_define,$filter=null){ $thi

  • 玩转Koa之koa-router原理解析

    一.前言 Koa为了保持自身的简洁,并没有捆绑中间件.但是在实际的开发中,我们需要和形形色色的中间件打交道,本文将要分析的是经常用到的路由中间件 -- koa-router. 如果你对Koa的原理还不了解的话,可以先查看Koa原理解析. 二.koa-router概述 koa-router的源码只有两个文件:router.js和layer.js,分别对应Router对象和Layer对象. Layer对象是对单个路由的管理,其中包含的信息有路由路径(path).路由请求方法(method)和路由执行

  • SpringCloud配置刷新原理解析

    我们知道在SpringCloud中,当配置变更时,我们通过访问http://xxxx/refresh,可以在不启动服务的情况下获取最新的配置,那么它是如何做到的呢,当我们更改数据库配置并刷新后,如何能获取最新的数据源对象呢?下面我们看SpringCloud如何做到的. 一.环境变化 1.1.关于ContextRefresher 当我们访问/refresh时,会被RefreshEndpoint类所处理.我们来看源代码: /* * Copyright 2013-2014 the original a

  • 重学JS之显示强制类型转换详解

    ToString ToString负责处理非字符串到字符串的强制类型转换,常用的字符串化方法String().toString(). 基本类型值的字符串化规则: null转换为'null' undefined转换为'undefined' true转化为'true' 数字的字符串化遵循通用规则,极大值或者极小值采用科学计数法表示 普通对象在字符串化时,实际执行Object.prototype.toString(),返回该对象的类型[object type],例如: var test = {a :

  • 微信小程序wxml列表渲染原理解析

    这篇文章主要介绍了微信小程序wxml列表渲染原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 列表渲染存在的意义 以电商为例,我们希望渲染5个商品,而又希望容易改变,我们就要在wxml中动态添加. <view> <block wx:for="{{products}}" wx:for-item="item" wx:key="index"> <view>{{

随机推荐