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, reverse, NULL, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(Collection, reversed, NULL, ZEND_ACC_PUBLIC)
|
PHP_ME(Collection, reversed, NULL, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(Collection, shuffle, 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, set, key_value_arginfo, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(Collection, single, predicate_arginfo, ZEND_ACC_PUBLIC)
|
PHP_ME(Collection, single, predicate_arginfo, ZEND_ACC_PUBLIC)
|
||||||
PHP_ME(Collection, slice, keys_arginfo, ZEND_ACC_PUBLIC)
|
PHP_ME(Collection, slice, keys_arginfo, ZEND_ACC_PUBLIC)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <php.h>
|
#include <php.h>
|
||||||
|
#include <ext/standard/php_mt_rand.h>
|
||||||
|
|
||||||
#include "php_collections.h"
|
#include "php_collections.h"
|
||||||
#include "php_collections_me.h"
|
#include "php_collections_me.h"
|
||||||
|
@ -1479,7 +1480,40 @@ PHP_METHOD(Collection, reversed)
|
||||||
|
|
||||||
PHP_METHOD(Collection, shuffle)
|
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)
|
PHP_METHOD(Collection, set)
|
||||||
|
|
|
@ -84,6 +84,7 @@ PHP_METHOD(Collection, retainAll);
|
||||||
PHP_METHOD(Collection, reverse);
|
PHP_METHOD(Collection, reverse);
|
||||||
PHP_METHOD(Collection, reversed);
|
PHP_METHOD(Collection, reversed);
|
||||||
PHP_METHOD(Collection, shuffle);
|
PHP_METHOD(Collection, shuffle);
|
||||||
|
PHP_METHOD(Collection, shuffled);
|
||||||
PHP_METHOD(Collection, set);
|
PHP_METHOD(Collection, set);
|
||||||
PHP_METHOD(Collection, single);
|
PHP_METHOD(Collection, single);
|
||||||
PHP_METHOD(Collection, slice);
|
PHP_METHOD(Collection, slice);
|
||||||
|
|
|
@ -695,11 +695,18 @@ class Collection implements ArrayAccess, Countable
|
||||||
function set($key, $value) {}
|
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
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
function shuffle() {}
|
function shuffled() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the single element matching the given predicate, or null if there is no or more than
|
* 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