英文:
How can I sort string array by character a in golang
问题
我正在解决一个算法问题,需要使用Go语言对其进行编码。在这个问题中,我需要按字符"a"对给定的字符串数组进行排序。如果需要详细讨论问题的细节。
问题:
编写一个函数,按照单词中字符"a"的数量(降序)对一组单词进行排序。如果某些单词包含相同数量的字符"a",则需要按照它们的长度进行排序。
输入:
["aaaasd", "a", "aab", "aaabcd", "ef", "cssssssd", "fdz", "kf", "zc", "lklklklklklklklkl", "l"]
输出:
["aaaasd", "aaabcd", "aab", "a", "lklklklklklklklkl", "cssssssd", "fdz", "ef", "kf", "zc", "l"]
我的解决方案:
func main() {
arr := []string{"aaaasd", "a", "aab", "aaabcd", "ef", "cssssssd", "fdz", "kf", "zc", "lklklklklklklklkl", "l"}
fmt.Println(mostFrequent(arr))
}
type FrequencyAndLength struct {
slice string
mostFrequent int
len int
}
func mostFrequent(arr []string) []FrequencyAndLength {
testArray := []FrequencyAndLength{}
for _, a := range arr {
testArray = append(testArray, FrequencyAndLength{
slice: a,
mostFrequent: strings.Count(a, "a"),
len: len(a),
})
}
fmt.Println(testArray)
return testArray
}
我目前正在获取每个元素中"a"的数量和长度。我需要首先按照"a"的数量排序,如果"a"的数量相同,则按照长度进行排序(降序),但是在逻辑上我卡住了。
英文:
I am working on an algorithm question and I need to encode it with golang. In this question I need to sort a given string array by character 'a'. If I need to talk about the details of the question.
Question:
Write a function that sorts a bunch of words by the number of character “a”s within the
word (decreasing order). If some words contain the same amount of character “a”s then you
need to sort those words by their lengths
Input
["aaaasd", "a", "aab", "aaabcd", "ef", "cssssssd", "fdz", "kf", "zc", "lklklklklklklklkl", "l"]
Output:
["aaaasd", "aaabcd", "aab", "a", "lklklklklklklklkl", "cssssssd", "fdz", "ef", "kf", "zc", "l"]
My Solution:
func main() {
arr := []string{"aaaasd", "a", "aab", "aaabcd", "ef", "cssssssd", "fdz", "kf", "zc", "lklklklklklklklkl", "l"}
fmt.Println(mostFrequent(arr))
}
type FrequencyAndLength struct {
slice string
mostFrequent int
len int
}
func mostFrequent(arr []string) []FrequencyAndLength { // assuming no
testArray := []FrequencyAndLength{}
for _, a := range arr {
testArray = append(testArray, FrequencyAndLength{
slice: a,
mostFrequent: strings.Count(a, "a"),
len: len(a),
})
}
fmt.Println(testArray)
return testArray
}
I'm currently getting the number of a and the length of each element in it. I need to sort first by the number of a, then by length if there are even numbers of a, in descending order, but logically I'm stuck here.
答案1
得分: 5
使用sort.Slice()
函数可以按照自定义逻辑对任意切片进行排序。该函数需要一个定义两个元素之间“小于”关系的函数作为参数。
在你的情况下,如果一个值包含更多的a
字符,则认为它小于另一个值;如果计数相等,则比较它们的长度。可以使用strings.Count()
函数来计算子字符串的数量。要获取字符串的长度,可以使用内置的len()
函数,但请注意,len()
返回的是UTF-8编码的字节长度,而不是字符数。对于字符数,可以使用utf8.RuneCountInString()
函数。
例如:
in := []string{"aaaasd", "a", "aab", "aaabcd", "ef", "cssssssd", "fdz", "kf", "zc", "lklklklklklklklkl", "l"}
sort.Slice(in, func(i, j int) bool {
s1, s2 := in[i], in[j]
count1, count2 := strings.Count(s1, "a"), strings.Count(s2, "a")
if count1 != count2 {
return count1 > count2
}
return utf8.RuneCountInString(s1) > utf8.RuneCountInString(s2)
})
fmt.Println(in)
这将输出(在Go Playground上尝试):
[aaaasd aaabcd aab a lklklklklklklklkl cssssssd fdz ef kf zc l]
请注意,包含相同数量的a
且长度相等的元素之间的顺序是未指定的。如果你希望它们按照输入切片中的顺序排列,可以使用sort.SliceStable()
而不是sort.Slice()
。
还请注意,我们的自定义逻辑并不复杂,但也不是简单的。该函数可能会多次调用以比较元素,并且同一个元素可能会被多次传递(询问)。如果输入切片很大,为每个元素计算a
的数量和字符长度一次,并将它们存储在一个映射中(例如map),然后在less()
函数中只查询这些预先计算的数据,可能会更有效率。
以下是示例代码:
// 预先计算
type info struct{ count, length int }
calculated := map[string]info{}
for _, s := range in {
calculated[s] = info{
count: strings.Count(s, "a"),
length: utf8.RuneCountInString(s),
}
}
sort.Slice(in, func(i, j int) bool {
inf1, inf2 := calculated[in[i]], calculated[in[j]]
if inf1.count != inf2.count {
return inf1.count > inf2.count
}
return inf1.length > inf2.length
})
这将输出相同的结果。在Go Playground上尝试一下。
英文:
Use sort.Slice()
to sort any slice by a custom logic. This function expects a function that defines the "less" relation between 2 elements.
In your case a value is less than another if it contains more a
characters, or if the count is equal, then resort to comparing their lengths. To count substrings, use strings.Count()
. To get the length of a string
, use the builtin len()
function, but note that len()
returns the UTF-8 encoded byte length, not the number of runes. For the letter, use utf8.RuneCountInString()
.
For example:
in := []string{"aaaasd", "a", "aab", "aaabcd", "ef", "cssssssd", "fdz", "kf", "zc", "lklklklklklklklkl", "l"}
sort.Slice(in, func(i, j int) bool {
s1, s2 := in[i], in[j]
count1, count2 := strings.Count(s1, "a"), strings.Count(s2, "a")
if count1 != count2 {
return count1 > count2
}
return utf8.RuneCountInString(s1) > utf8.RuneCountInString(s2)
})
fmt.Println(in)
This will output (try it on the Go Playground):
[aaaasd aaabcd aab a lklklklklklklklkl cssssssd fdz ef kf zc l]
Note that the order between elements that contain equal number of a
's and have equal length is unspecified. If you want them in the same order as in your input slice, use sort.SliceStable()
instead of sort.Slice()
.
Also note that our custom logic is not complex but not trivial either. The function may be called many times to compare elements, and the same element may be passed (asked) multiple times. If the input slice is big, it may be profitable to calculate the numer of a
's and the rune length once for each element, store them in a map for example, and just query this precalculated data in the less()
function.
This is how it could look like:
// Pre-calculate
type info struct{ count, length int }
calculated := map[string]info{}
for _, s := range in {
calculated展开收缩 = info{
count: strings.Count(s, "a"),
length: utf8.RuneCountInString(s),
}
}
sort.Slice(in, func(i, j int) bool {
inf1, inf2 := calculated[in[i]], calculated[in[j]]
if inf1.count != inf2.count {
return inf1.count > inf2.count
}
return inf1.length > inf2.length
})
This outputs the same. Try it on the Go Playground.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论