PHP 7.3.0之前的版本获取数组第一个和最后一个元素的key的几种方法。
$a = [
'one' => 1,
'two' => 2,
'three' => 3
];
方法一
$first = reset($a);
$first_key = key($a);
$last = end($a);
$last_key = key($a);
方法二
$keys = array_keys($a);
$first = reset($keys);
$last = end($keys);
可以使用array_keys(),但是这样做的效率可能相当低。
也可以使用reset()和key(),但是这可能会改变内部数组指针。
PHP 7.3.0 加入两个函数解决这些问题了。
see https://www.php.net/manual/zh/function.array-key-last.php
- array_key_first
- array_key_last
看看它们是如果实现的。源码加了一些中文注释方便理解。
文件在 array.c : 3952
PHP_FUNCTION(array_key_first)
{
zval *stack;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ARRAY(stack)
ZEND_PARSE_PARAMETERS_END();
HashTable *target_hash = Z_ARRVAL_P (stack);
HashPosition pos = 0;
zend_hash_get_current_key_zval_ex(target_hash, return_value, &pos);
}
ZEND_API void ZEND_FASTCALL zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos)
{
uint32_t idx = *pos;
Bucket *p;
IS_CONSISTENT(ht);
if (idx >= ht->nNumUsed) {
ZVAL_NULL(key);
} else {
if (idx == 0) {
idx = _zend_hash_get_first_pos(ht);
if (idx >= ht->nNumUsed) {
ZVAL_NULL(key);
return;
}
}
p = ht->arData + idx;
if (p->key) {
ZVAL_STR_COPY(key, p->key);
} else {
ZVAL_LONG(key, p->h);
}
}
}
PHP_FUNCTION(array_key_last)
{
zval *stack;
HashPosition pos;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ARRAY(stack)
ZEND_PARSE_PARAMETERS_END();
HashTable *target_hash = Z_ARRVAL_P (stack);
zend_hash_internal_pointer_end_ex(target_hash, &pos);
zend_hash_get_current_key_zval_ex(target_hash, return_value, &pos);
}
ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
{
uint32_t idx;
IS_CONSISTENT(ht);
HT_ASSERT(ht, &ht->nInternalPointer != pos || GC_REFCOUNT(ht) == 1);
idx = ht->nNumUsed;
while (idx > 0) {
idx--;
if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
*pos = idx;
return;
}
}
*pos = ht->nNumUsed;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)