diff --git a/src/common/Utilities/Containers.h b/src/common/Utilities/Containers.h index 64f3ee9dd52..6cd95676bdf 100644 --- a/src/common/Utilities/Containers.h +++ b/src/common/Utilities/Containers.h @@ -53,17 +53,29 @@ namespace Trinity return size; } + // resizes to have at most elements + // if it has more than elements, the elements to keep are selected randomly template void RandomResize(C& container, std::size_t requestedSize) { - uint32 currentSize = uint32(Size(container)); - while (currentSize > requestedSize) + static_assert(std::is_base_of::iterator_category>::value, "Invalid container passed to Trinity::Containers::RandomResize"); + if (Size(container) <= requestedSize) + return; + auto keepIt = std::begin(container), curIt = std::begin(container); + uint32 elementsToKeep = requestedSize, elementsToProcess = Size(container); + while (elementsToProcess) { - auto itr = std::begin(container); - std::advance(itr, urand(0, currentSize - 1)); - container.erase(itr); - --currentSize; + // this element has chance (elementsToKeep / elementsToProcess) of being kept + if (urand(1, elementsToProcess) <= elementsToKeep) + { + *keepIt = std::move(*curIt); + ++keepIt; + --elementsToKeep; + } + ++curIt; + --elementsToProcess; } + container.erase(keepIt, std::end(container)); } template