add `shuffle()` and `shuffled()`
This commit is contained in:
parent
8ca9980472
commit
bf4eaca339
|
@ -198,6 +198,7 @@ const zend_function_entry collection_methods[] = {
|
|||
PHP_ME(Collection, reverse, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, reversed, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, shuffle, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, shuffled, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, set, key_value_arginfo, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, single, predicate_arginfo, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(Collection, slice, keys_arginfo, ZEND_ACC_PUBLIC)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
//
|
||||
|
||||
#include <php.h>
|
||||
#include <ext/standard/php_mt_rand.h>
|
||||
|
||||
#include "php_collections.h"
|
||||
#include "php_collections_me.h"
|
||||
|
@ -1479,7 +1480,40 @@ PHP_METHOD(Collection, reversed)
|
|||
|
||||
PHP_METHOD(Collection, shuffle)
|
||||
{
|
||||
|
||||
zend_array* current = COLLECTION_FETCH_CURRENT();
|
||||
uint32_t num_elements = zend_hash_num_elements(current);
|
||||
ARRAY_NEW(shuffled, num_elements);
|
||||
ZEND_HASH_FOREACH_VAL(current, zval* val)
|
||||
zend_hash_next_index_insert(shuffled, val);
|
||||
ZEND_HASH_FOREACH_END();
|
||||
size_t offset = 0;
|
||||
Bucket* bucket = shuffled->arData;
|
||||
for (; offset < num_elements - 1; ++offset) {
|
||||
zend_long rand_idx = php_mt_rand_range(offset, num_elements - 1);
|
||||
zend_hash_bucket_renum_swap(&bucket[offset], &bucket[rand_idx]);
|
||||
}
|
||||
if (GC_REFCOUNT(current) > 1)
|
||||
GC_DELREF(current);
|
||||
else
|
||||
zend_hash_destroy(current);
|
||||
COLLECTION_FETCH_CURRENT() = shuffled;
|
||||
}
|
||||
|
||||
PHP_METHOD(Collection, shuffled)
|
||||
{
|
||||
zend_array* current = COLLECTION_FETCH_CURRENT();
|
||||
uint32_t num_elements = zend_hash_num_elements(current);
|
||||
ARRAY_NEW(shuffled, num_elements);
|
||||
ZEND_HASH_FOREACH_VAL(current, zval* val)
|
||||
zend_hash_next_index_insert(shuffled, val);
|
||||
ZEND_HASH_FOREACH_END();
|
||||
size_t offset = 0;
|
||||
Bucket* bucket = shuffled->arData;
|
||||
for (; offset < num_elements - 1; ++offset) {
|
||||
zend_long rand_idx = php_mt_rand_range(offset, num_elements - 1);
|
||||
zend_hash_bucket_renum_swap(&bucket[offset], &bucket[rand_idx]);
|
||||
}
|
||||
RETVAL_NEW_COLLECTION(shuffled);
|
||||
}
|
||||
|
||||
PHP_METHOD(Collection, set)
|
||||
|
|
|
@ -84,6 +84,7 @@ PHP_METHOD(Collection, retainAll);
|
|||
PHP_METHOD(Collection, reverse);
|
||||
PHP_METHOD(Collection, reversed);
|
||||
PHP_METHOD(Collection, shuffle);
|
||||
PHP_METHOD(Collection, shuffled);
|
||||
PHP_METHOD(Collection, set);
|
||||
PHP_METHOD(Collection, single);
|
||||
PHP_METHOD(Collection, slice);
|
||||
|
|
|
@ -695,11 +695,18 @@ class Collection implements ArrayAccess, Countable
|
|||
function set($key, $value) {}
|
||||
|
||||
/**
|
||||
* Randomly shuffles elements in this collection.
|
||||
* Randomly shuffles elements in this collection. Keys will be discarded.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function shuffle() {}
|
||||
|
||||
/**
|
||||
* Returns a shuffled copy of this collection. Keys will be discarded.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
function shuffle() {}
|
||||
function shuffled() {}
|
||||
|
||||
/**
|
||||
* Returns the single element matching the given predicate, or null if there is no or more than
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
--TEST--
|
||||
Test Collection::shuffle() and Collection::shuffled().
|
||||
--FILE--
|
||||
<?php
|
||||
$array = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5];
|
||||
|
||||
for ($i = 0; ; ++$i) {
|
||||
$collection = Collection::init($array);
|
||||
$collection->shuffle();
|
||||
if ($collection != array_values($array))
|
||||
break;
|
||||
if ($i > 10) {
|
||||
echo 'Collection::shuffle() failed.', PHP_EOL;
|
||||
exit;
|
||||
}
|
||||
}
|
||||
if (array_sum($array) != array_sum($collection->toArray()))
|
||||
echo 'Collection::shuffle() failed.', PHP_EOL;
|
||||
|
||||
for ($i = 0; ; ++$i) {
|
||||
$reversed = Collection::init($array)->shuffled();
|
||||
if ($reversed != array_values($array))
|
||||
break;
|
||||
if ($i > 10) {
|
||||
echo 'Collection::shuffled() failed.', PHP_EOL;
|
||||
exit;
|
||||
}
|
||||
}
|
||||
if (array_sum($array) != array_sum($reversed->toArray()))
|
||||
echo 'Collection::shuffled() failed.', PHP_EOL;
|
||||
?>
|
||||
--EXPECT--
|
Reference in New Issue