blog.stackframe.dev

[PHP 8.1] array_is_list() 함수 추가

PHP 8.1에는 다른 흥미로운 기능들도 많지만 그 중에 소소하게 귀찮음을 덜어줄 array_is_list() 함수가 생겼다. 이 함수는 배열이 리스트 형태로 되어있는지 검사한다. 예전에는 동일한 기능을 하는 함수를 직접 구현해야 했지만 이제 PHP 언어 자체에서 이 기능을 지원한다.

PHP 자체에서 지원해줌으로 생기는 이점은 크게 2가지다.

  • 직접 구현함으로 생기는 귀찮음을 덜고 버그가 생길 가능성을 줄일 수 있다.
  • array_is_list() 함수는 C 언어로 구현되어 있기 때문에 빠르다.

마지막은 벤치마크가 아닌 실제 사용에서는 체감되지 않을 것이다.

이 함수 사용에 주의해야 할 점은 배열 내부의 순서도 영향을 미친다는 점이다:

<?php
$arr1 = [1,2,3,4];
$arr2 = [0 => 1, 2 => 2, 1 => 3];

var_dump(array_is_list($arr1));
var_dump(array_is_list($arr2));

위의 코드를 실행시키면 $arr1true, $arr2false가 나온다.

Zend/zend_hash.h 파일에 array_is_list() 함수의 원형인 zend_array_is_list()가 있다. 이 함수 내용을 보면 아래와 같이 FOREACH로 키가 순서대로 들어있는지 확인하기 때문에 내부 순서 또한 정렬되어야 한다:

static zend_always_inline bool zend_array_is_list(zend_array *array)
{
        zend_long expected_idx = 0;
        zend_long num_idx;
        zend_string* str_idx;
        /* Empty arrays are lists */
        if (zend_hash_num_elements(array) == 0) {
                return 1;
        }

        /* Packed arrays are lists */
        if (HT_IS_PACKED(array) && HT_IS_WITHOUT_HOLES(array)) {
                return 1;
        }

        /* Check if the list could theoretically be repacked */
        ZEND_HASH_FOREACH_KEY(array, num_idx, str_idx) {
                if (str_idx != NULL || num_idx != expected_idx++) {
                        return 0;
                }
        } ZEND_HASH_FOREACH_END();

        return 1;
}

그러므로 정렬이 되어있지 않은 리스트에 array_is_list() 함수를 사용하려면 먼저 ksort() 함수로 다시 정렬하면 된다.

댓글