(sequence: Iterable<T>, limit = 0)
| 1048 | * @param limit - Defaults to `0`. If nonzero shuffle will slice the randomized array e.g, `.slice(0, limit)` otherwise will return the entire randomized array. |
| 1049 | */ |
| 1050 | export function shuffle<T>(sequence: Iterable<T>, limit = 0): Array<T> { |
| 1051 | const items = Array.from(sequence); class="cm">// shallow copy in order to never shuffle the input |
| 1052 | |
| 1053 | if (limit > items.length) { |
| 1054 | throw new MongoRuntimeError(class="st">'Limit must be less than the number of items'); |
| 1055 | } |
| 1056 | |
| 1057 | let remainingItemsToShuffle = items.length; |
| 1058 | const lowerBound = limit % items.length === 0 ? 1 : items.length - limit; |
| 1059 | while (remainingItemsToShuffle > lowerBound) { |
| 1060 | class="cm">// Pick a remaining element |
| 1061 | const randomIndex = Math.floor(Math.random() * remainingItemsToShuffle); |
| 1062 | remainingItemsToShuffle -= 1; |
| 1063 | |
| 1064 | class="cm">// And swap it with the current element |
| 1065 | const swapHold = items[remainingItemsToShuffle]; |
| 1066 | items[remainingItemsToShuffle] = items[randomIndex]; |
| 1067 | items[randomIndex] = swapHold; |
| 1068 | } |
| 1069 | |
| 1070 | return limit % items.length === 0 ? items : items.slice(lowerBound); |
| 1071 | } |
| 1072 | |
| 1073 | /** |
| 1074 | * TODO(NODE-4936): read concern eligibility for commands should be codified in command construction |
no outgoing calls
no test coverage detected