筚路蓝缕,以启山林。抚有蛮夷,以属华夏。不鸣则已,一鸣惊人。
——《左传`宣公十二年》
之前有人(面试官)提过这个问题,刚想到要不总结一下,顺手来实现下看看。
map遍历数据本身就是无序的,我们不能直接对map本身的存储结构进行直接操作,但可在它所存储的数据上做手脚。
多个情况的解决方案如下,直接上代码
func main() {
m := make(map[int]string)
m[1] = "A"
m[5] = "B"
m[2] = "B"
m[3] = "C"
m[4] = "A"
for k, v := range m {
fmt.Println(k, v) // 多次运行,每次输出的都是key无序的
}
// 输出map中的数据,按key排序
count := len(m)
keySlice := make([]int, 0, count) // 用于单独存放key的切片,按key时只看该行即可
valSlice := make([]string, 0, count) // 用于单独存放value值的切片
valMap := make(map[string][]int) // 用于存放原map的value-key映射(以value获取key集合),key值相同时对应多个value值
for k := range m {
keySlice = append(keySlice, k) // 按key时只看该行即可
valSlice = append(valSlice, m[k])
if _, ok := valMap[m[k]]; ok {
valMap[m[k]] = append(valMap[m[k]], k)
continue
}
valMap[m[k]] = []int{k}
}
sort.Ints(keySlice)
fmt.Println("获取按key排序后数据:")
for _, v := range keySlice {
fmt.Println(v, m[v])
}
// 按value排序,方式1
sort.Strings(valSlice)
fmt.Println("获取按value排序后数据(只需要value时):")
for _, v := range valSlice {
fmt.Println(v)
}
fmt.Println("获取按value排序后数据(key、value都需要时):")
for _, v := range valSlice {
if _, ok := valMap[v]; ok {
fmt.Println(valMap[v], v) // 如要继续分别按每个key输出,可以if len(valMap[v]) > 1 {...}进行判断操作
delete(valMap, v)
continue
}
}
// 按value排序,方式2
sortList, index := make(KVList, count), 0
for k, v := range m {
sortList[index] = KV{k, v}
if index < count {
index++
}
}
sort.Sort(sortList)
fmt.Println("获取按value排序后数据(key、value都需要时):")
for _, v := range sortList {
fmt.Println(v.K,m[v.K])
}
}
// 把map的每一对键值作为对象存起来
type KV struct {
K int
V string
}
type KVList []KV
func (l KVList) Swap(i, j int) {
l[i], l[j] = l[j], l[i]
}
func (l KVList) Len() int {
return len(l)
}
func (l KVList) Less(i, j int) bool {
return l[i].V < l[j].V
}
控制台:
1 A
5 B
2 B
3 C
4 A
获取按key排序后数据:
1 A
2 B
3 C
4 A
5 B
获取按value排序后数据(只需要value时):
A
A
B
B
C
获取按value排序后数据(key、value都需要时):
[1 4] A
[5 2] B
[3] C
获取按value排序后数据(key、value都需要时):
4 A
1 A
5 B
2 B
3 C
当然,排序时也可自己写排序方法代替sort库的Sort方法。