Variant ArrayUtil::Shuffle(const Array& input) { int count = input.size(); if (count == 0) { return input; } std::vector<ssize_t> indices; indices.reserve(count); auto pos_limit = input->iter_end(); for (ssize_t pos = input->iter_begin(); pos != pos_limit; pos = input->iter_advance(pos)) { indices.push_back(pos); } php_array_data_shuffle(indices); if (input.isVecArray()) { VecArrayInit ret(count); for (int i = 0; i < count; i++) { ssize_t pos = indices[i]; ret.append(input->atPos(pos)); } return ret.toVariant(); } else if (input.isDict()) { DictInit ret(count); for (int i = 0; i < count; i++) { ssize_t pos = indices[i]; ret.append(input->atPos(pos)); } return ret.toVariant(); } else if (input.isKeyset()) { KeysetInit ret(count); for (int i = 0; i < count; i++) { ssize_t pos = indices[i]; ret.add(input->atPos(pos)); } return ret.toVariant(); } else { PackedArrayInit ret(count); for (int i = 0; i < count; i++) { ssize_t pos = indices[i]; ret.appendWithRef(input->atPos(pos)); } return ret.toVariant(); } }
Variant ArrayUtil::Shuffle(CArrRef input) { int count = input.size(); if (count == 0) { return input; } std::vector<ssize_t> indices; indices.reserve(count); for (ssize_t pos = input->iter_begin(); pos != ArrayData::invalid_index; pos = input->iter_advance(pos)) { indices.push_back(pos); } php_array_data_shuffle(indices); Array ret = Array::Create(); for (int i = 0; i < count; i++) { ssize_t pos = indices[i]; ret.appendWithRef(input->getValueRef(pos)); } return ret; }
Variant ArrayUtil::RandomKeys(const Array& input, int num_req /* = 1 */) { int count = input.size(); if (num_req <= 0 || num_req > count) { raise_warning("Second argument has to be between 1 and the " "number of elements in the array"); return init_null(); } if (num_req == 1) { // Iterating through the counter is correct but a bit inefficient // compared to being able to access the right offset into array data, // but necessary for this code to be agnostic to the array's internal // representation. Assuming uniform distribution, we'll expect to // iterate through half of the array's data. ssize_t index = f_rand(0, count-1); ssize_t pos = input->iter_begin(); while (index--) { pos = input->iter_advance(pos); } return input->getKey(pos); } std::vector<ssize_t> indices; indices.reserve(count); auto pos_limit = input->iter_end(); for (ssize_t pos = input->iter_begin(); pos != pos_limit; pos = input->iter_advance(pos)) { indices.push_back(pos); } php_array_data_shuffle(indices); PackedArrayInit ret(num_req); for (int i = 0; i < num_req; i++) { ssize_t pos = indices[i]; ret.append(input->getKey(pos)); } return ret.toVariant(); }