Skip to content

Commit

Permalink
perf(shuffle): use the Fisher-Yates algorithm (#76)
Browse files Browse the repository at this point in the history
  • Loading branch information
eumkz authored Jul 5, 2024
1 parent 5dc3e71 commit 27b1710
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
19 changes: 14 additions & 5 deletions src/random/shuffle.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
export function shuffle<T>(array: readonly T[]): T[] {
return array
.map(a => ({ rand: Math.random(), value: a }))
.sort((a, b) => a.rand - b.rand)
.map(a => a.value)
import * as _ from 'radashi'

export function shuffle<T>(
array: readonly T[],
random: (min: number, max: number) => number = _.random,
): T[] {
const newArray = array.slice()
for (let idx = 0, randomIdx: number, item: T; idx < array.length; idx++) {
randomIdx = random(0, array.length - 1)
item = newArray[randomIdx]
newArray[randomIdx] = newArray[idx]
newArray[idx] = item
}
return newArray
}
10 changes: 10 additions & 0 deletions tests/random/shuffle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,14 @@ describe('shuffle', () => {
expect(list).not.toBe(result)
expect(list).toEqual([1, 2, 3, 4, 5])
})
test('uses custom random function when provided', () => {
const list = [1, 2, 3, 4, 5]
const mockRandom = vi.fn(() => 1)
const result = _.shuffle(list, mockRandom)

expect(mockRandom).toHaveBeenCalled()
expect(result).not.toEqual(list)
expect(result.length).toBe(list.length)
expect(new Set(result)).toEqual(new Set(list))
})
})

0 comments on commit 27b1710

Please sign in to comment.