GolangNote

Golang笔记

Golang 随机打乱数组/Slice

Permalink2

给定一个数组/列表/Slice,随机打乱顺序

Go: 随机打乱Slice顺序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    slice := []interface{}{"a", "b", "c", "d", "e", "f"}
    Shuffle(slice)
    fmt.Println(slice)
    for _, v := range slice {
        fmt.Println(v.(string))
    }
}

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

运行,每次输出都不同:

plaintext: 随机打乱Slice顺序结果输出
1
2
3
4
5
6
7
[f c e d b a]
f
c
e
d
b
a

更新

Go 1.10 后可使用 math/rand 库的 Shuffle 函数实现。

Go: rand.Shuffle
1
2
3
4
5
6
func randShuffle(slice []interface{}) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	r.Shuffle(len(slice), func(i, j int) {
		slice[i], slice[j] = slice[j], slice[i]
	})
}

代码更简单。

目前最新版本 (go version go1.17.3 darwin/amd64) 的基准测试结果

plaintext:
1
2
3
4
5
6
7
8
9
goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
Benchmark_my_shuffle
Benchmark_my_shuffle-8     	  115099	     10043 ns/op	    5376 B/op	       1 allocs/op
Benchmark_rand_shuffle
Benchmark_rand_shuffle-8   	  115148	      9974 ns/op	    5376 B/op	       1 allocs/op
PASS
ok  	command-line-arguments	2.526s

结果显示,rand.Shuffle 的性能已经很棒,略微超出。

测试代码

Go: randShuffle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func myShuffle(slice []interface{}) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for len(slice) > 0 {
		n := len(slice)
		randIndex := r.Intn(n)
		slice[n-1], slice[randIndex] = slice[randIndex], slice[n-1]
		slice = slice[:n-1]
	}
}

func randShuffle(slice []interface{}) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	r.Shuffle(len(slice), func(i, j int) {
		slice[i], slice[j] = slice[j], slice[i]
	})
}

本文网址: https://golangnote.com/topic/260.html 转摘请注明来源

Related articles

Golang Range 的性能提升Tip

Go 语言里使用 range 可以方便遍历数组(array)、切片(slice)、字典(map)和信道(chan)。这里主要关注他们的性能。...

Comments

There are 2 Comments to "Golang 随机打乱数组/Slice"

1 smallwhite says:
回复

为什么不用 rand.Shuffle ??

2 GolangNote says:
回复

@smallwhite 一丁点性能改善

更新:Go 1.10 后,两者性能差别很小,可以忽略不计

plaintext:
1
2
3
4
5
6
7
8
9
goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
Benchmark_my_shuffle
Benchmark_my_shuffle-8     	  115099	     10043 ns/op	    5376 B/op	       1 allocs/op
Benchmark_rand_shuffle
Benchmark_rand_shuffle-8   	  115148	      9974 ns/op	    5376 B/op	       1 allocs/op
PASS
ok  	command-line-arguments	2.526s

Write a Comment to "Golang 随机打乱数组/Slice"

Submit Comment Login
Based on Golang + fastHTTP + sdb | go1.18 Processed in 1ms