Skip to content

An Implementation of random.shuffle in golang

Introduction

Golang is a powerful programming language that has gained a lot of popularity in recent years. One of the most interesting features of Golang is its built-in support for concurrency. Another feature that makes Golang stand out is its standard library which is packed with useful functions. In this blog post, we’ll be discussing an implementation of the random.shuffle function in Golang similar to random.shuffle in Python.

The naive approach

func Shuffle(vals []int) []int {
  r := rand.New(rand.NewSource(time.Now().Unix()))
  ret := make([]int, len(vals))
  n := len(vals)
  for i := 0; i < n; i++ {
    randIndex := r.Intn(len(vals))
    ret[i] = vals[randIndex]
    vals = append(vals[:randIndex], vals[randIndex+1:]...)
  }
  return ret
}

or use rand.Perm() to do this a bit more efficiently

func Shuffle(vals []int) []int {
  r := rand.New(rand.NewSource(time.Now().Unix()))
  ret := make([]int, len(vals))
  perm := r.Perm(len(vals))
  for i, randIndex := range perm {
    ret[i] = vals[randIndex]
  }
  return ret
}

Shuffling without creating a new slice or array

func Shuffle(vals []int) {
  r := rand.New(rand.NewSource(time.Now().Unix()))
  for len(vals) > 0 {
    n := len(vals)
    randIndex := r.Intn(n)
    vals[n-1], vals[randIndex] = vals[randIndex], vals[n-1]
    vals = vals[:n-1]
  }
}

Using Generics to support different type of slice

// for go 1.18+
func Shuffle [Tx any] (vals []Tx) []Tx {
    r := rand.New(rand.NewSource(time.Now().Unix()))
    ret := make([]Tx, len(vals))
    perm := r.Perm(len(vals))
    for i, randIndex := range perm {
        ret[i] = vals[randIndex]
    }
    return ret
}

reference

  • https://www.calhoun.io/how-to-shuffle-arrays-and-slices-in-go
Feedback