英文:
How to sort map by value and if value equals then by key in Go?
问题
我遇到了一个情况,我想要按值对地图进行排序,如果值相等,则按键排序。这里有一个输入和期望的输出示例。
import "fmt"
func main() {
wordFrequency := map[string]int{"banana": 3, "america": 2, "abb": 2, "test": 2, "car": 1}
fmt.Printf("%v", wordFrequency)
}
期望的输出:{"banana": 3, "abb": 2, "america": 2, "test": 2, "car": 1}
在这里,banana排在第一位,因为它的值是3。abb和america的值都是2,但是abb按升序排序,所以它排在前面。所以我的问题是如何实现这种行为,即首先按值对地图中的条目进行排序,如果值相等,则按键排序。我已经查看了相关文档和以前的问题,但没有直接解决这种情况的。如果由于Go中的地图数据结构而无法实现,我们如何使用其他结构高效地实现呢?
在Python 3中,我们可以按以下方式实现:
d = {'apple':2, 'banana':3, 'almond':2, 'beetroot':3, 'peach':4}
[k for k, v in sorted(d.items(), key=lambda item: (-item[1], item[0]))]
这是Python的等效问题的链接:链接
注意:这个问题问如何按值对地图进行排序。我的问题是特定于按值排序,然后按键排序(如果值相等)。
英文:
I came across a situation where I want to sort a map first by value and if the values are equal then by key in GO. Here is an example of input and expected output.
import "fmt"
func main() {
wordFrequency := map[string]int{"banana": 3, "america": 2, "abb": 2, "test": 2, "car": 1}
fmt.Printf("%v", wordFrequency)
}
Expected output : {"banana": 3,"abb": 2, "america": 2, "test": 2, "car": 1}
Here banana is at first because its value is 3. abb and america both value is 2 but abb comes first as sorted in ascender order. So my question is how to implement this behaviour where we sort the entries in map first by value and if value equals we sort them by key. I have checked related documentation and previous questions but none directly address this scenario. If it is not possible to do due to map data structure in Go, how can we do that efficiently with other structures?
In Python 3, we can do this in the following way
>>> d = {'apple':2, 'banana':3, 'almond':2, 'beetroot':3, 'peach':4}
>>> [k for k, v in sorted(d.iteritems(), key=lambda(k, v): (-v, k))]
['peach', 'banana', 'beetroot', 'almond', 'apple']
Here is a link for the equivalent question for Python link
N.B: This question asks how to sort map by value. My question is specific to sort by value and then key (if value equals).
答案1
得分: 2
你无法对 map
进行排序。
- 将
map
转换为键值对结构体的切片。 - 对切片进行排序(参见如何对具有多个排序参数的结构体进行排序?)
例如:
func main() {
wordFrequency := map[string]int{"banana": 3, "america": 2, "abb": 2, "test": 2, "car": 1}
vec := mapToSlice(wordFrequency)
sort.Slice(vec, func(i, j int) bool {
// 1. 值不同 - 按值排序(逆序)
if vec[i].value != vec[j].value {
return vec[i].value > vec[j].value
}
// 2. 只有值相同时 - 按键排序
return vec[i].key < vec[j].key
})
fmt.Printf("%v", vec)
}
func mapToSlice(in map[string]int) []KV {
vec := make([]KV, len(in))
i := 0
for k, v := range in {
vec[i].key = k
vec[i].value = v
i++
}
return vec
}
type KV struct {
key string
value int
}
输出结果为:
[{banana 3} {abb 2} {america 2} {test 2} {car 1}]
英文:
You can't sort a map
.
- Convert the
map
to a slice of key-value-pair structs. - Sort the slice (see also How to sort struct with multiple sort parameters?)
For example like this:
func main() {
wordFrequency := map[string]int{"banana": 3, "america": 2, "abb": 2, "test": 2, "car": 1}
vec := mapToSlice(wordFrequency)
sort.Slice(vec, func(i, j int) bool {
// 1. value is different - sort by value (in reverse order)
if vec[i].value != vec[j].value {
return vec[i].value > vec[j].value
}
// 2. only when value is the same - sort by key
return vec[i].key < vec[j].key
})
fmt.Printf("%v", vec)
}
func mapToSlice(in map[string]int) []KV {
vec := make([]KV, len(in))
i := 0
for k, v := range in {
vec[i].key = k
vec[i].value = v
i++
}
return vec
}
type KV struct {
key string
value int
}
Prints:
[{banana 3} {abb 2} {america 2} {test 2} {car 1}]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论