Skip to content

Commit 0ceb08f

Browse files
committed
Optimize array_unique() implementation
1 parent 37632e8 commit 0ceb08f

File tree

1 file changed

+7
-54
lines changed

1 file changed

+7
-54
lines changed

ext/standard/array.c

Lines changed: 7 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4504,31 +4504,12 @@ PHP_FUNCTION(array_change_key_case)
45044504
}
45054505
/* }}} */
45064506

4507-
struct bucketindex {
4508-
Bucket b;
4509-
unsigned int i;
4510-
};
4511-
4512-
static void array_bucketindex_swap(void *p, void *q) /* {{{ */
4513-
{
4514-
struct bucketindex *f = (struct bucketindex *)p;
4515-
struct bucketindex *g = (struct bucketindex *)q;
4516-
struct bucketindex t;
4517-
t = *f;
4518-
*f = *g;
4519-
*g = t;
4520-
}
4521-
/* }}} */
4522-
45234507
/* {{{ proto array array_unique(array input [, int sort_flags])
45244508
Removes duplicate values from array */
45254509
PHP_FUNCTION(array_unique)
45264510
{
45274511
zval *array;
4528-
uint32_t idx;
4529-
Bucket *p;
4530-
struct bucketindex *arTmp, *cmpdata, *lastkept;
4531-
unsigned int i;
4512+
Bucket *p, *lastkept = NULL;
45324513
zend_long sort_type = PHP_SORT_STRING;
45334514
bucket_compare_func_t cmp;
45344515

@@ -4585,44 +4566,16 @@ PHP_FUNCTION(array_unique)
45854566
cmp = php_get_data_compare_func(sort_type, 0);
45864567

45874568
RETVAL_ARR(zend_array_dup(Z_ARRVAL_P(array)));
4569+
zend_hash_sort(Z_ARRVAL_P(return_value), cmp, /* reindex */ 0);
45884570

4589-
/* create and sort array with pointers to the target_hash buckets */
4590-
arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT);
4591-
for (i = 0, idx = 0; idx < Z_ARRVAL_P(array)->nNumUsed; idx++) {
4592-
p = Z_ARRVAL_P(array)->arData + idx;
4593-
if (Z_TYPE(p->val) == IS_UNDEF) continue;
4594-
if (Z_TYPE(p->val) == IS_INDIRECT && Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) continue;
4595-
arTmp[i].b = *p;
4596-
arTmp[i].i = i;
4597-
i++;
4598-
}
4599-
ZVAL_UNDEF(&arTmp[i].b.val);
4600-
zend_sort((void *) arTmp, i, sizeof(struct bucketindex),
4601-
(compare_func_t) cmp, (swap_func_t)array_bucketindex_swap);
46024571
/* go through the sorted array and delete duplicates from the copy */
4603-
lastkept = arTmp;
4604-
for (cmpdata = arTmp + 1; Z_TYPE(cmpdata->b.val) != IS_UNDEF; cmpdata++) {
4605-
if (cmp(&lastkept->b, &cmpdata->b)) {
4606-
lastkept = cmpdata;
4572+
ZEND_HASH_FOREACH_BUCKET(Z_ARRVAL_P(return_value), p) {
4573+
if (!lastkept || cmp(lastkept, p)) {
4574+
lastkept = p;
46074575
} else {
4608-
if (lastkept->i > cmpdata->i) {
4609-
p = &lastkept->b;
4610-
lastkept = cmpdata;
4611-
} else {
4612-
p = &cmpdata->b;
4613-
}
4614-
if (p->key == NULL) {
4615-
zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
4616-
} else {
4617-
if (Z_ARRVAL_P(return_value) == &EG(symbol_table)) {
4618-
zend_delete_global_variable(p->key);
4619-
} else {
4620-
zend_hash_del(Z_ARRVAL_P(return_value), p->key);
4621-
}
4622-
}
4576+
zend_hash_del_bucket(Z_ARRVAL_P(return_value), p);
46234577
}
4624-
}
4625-
pefree(arTmp, GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT);
4578+
} ZEND_HASH_FOREACH_END();
46264579
}
46274580
/* }}} */
46284581

0 commit comments

Comments
 (0)