英文:
When populating a slice with length set at runtime, do I absolutely need two loops, one for determining the length and one for populating?
问题
所以我有一个函数,它从字符串中删除标点符号,并将这些标点符号及其索引放入两个切片中:
func removeAndIndexPunctuation(word string) (string, []rune, []int) {
// Index punctuation
numberOfPunct := 0
for _, char := range word {
if unicode.IsPunct(char) {
numberOfPunct += 1
}
}
punctuations := make([]rune, numberOfPunct)
punctuationIndex := make([]int, numberOfPunct)
x := 0
for i, char := range word {
if unicode.IsPunct(char) {
punctuations[x] = char
punctuationIndex[x] = i
x += 1
}
}
// Remove all punctuation from word string
res := r.ReplaceAllString(word, "")
return res, punctuations, punctuationIndex
}
为了创建和填充这两个切片,我必须运行两个循环,一个用于计算标点符号的数量,以便我可以创建正确长度的数组,然后另一个循环基本上相同,只是现在我填充了这两个切片。
然而,在Python中,我不需要两个循环,因为Python支持"动态数组":
def removeAndIndexPunctuation(word):
punctuations = []
# Index punctuation
for i, char in enumerate(word):
if char in string.punctuation:
punctuations.append((char, i))
# Remove all punctuation from word string
word = word.encode("utf-8").translate(None, string.punctuation).decode("utf-8")
return word, punctuations
所以我只是想确认一下,在这种情况下,在Go中,我是否绝对需要两个循环,因为它不支持动态数组,或者我是否遗漏了什么?换句话说,如果我正在遍历一组字符并将其中一些添加到数组/切片中,我是否真的需要两个循环,一个用于计算字符的数量以设置切片的长度,另一个用于填充切片?
我来自Python,正在学习Go。
英文:
So I have a function that removes punctuation from a string and puts those punctuation characters and their index into two slices:
func removeAndIndexPunctuation(word string) (string, []rune, []int) {
// Index punctuation
numberOfPunct := 0
for _, char := range word {
if unicode.IsPunct(char) {
numberOfPunct += 1
}
}
punctuations := make([]rune, numberOfPunct)
punctuationIndex := make([]int, numberOfPunct)
x := 0
for i, char := range word {
if unicode.IsPunct(char) {
punctuations[x] = char
punctuationIndex[x] = i
x += 1
}
}
// Remove all punctuation from word string
res := r.ReplaceAllString(word, "")
return res, punctuations, punctuationIndex
}
In order to make and populate the slices I have to run two for loops, one for counting the number of punctuations so I can make the array the correct length and then another that's pretty much the same except now I populate the slices.
In Python though I don't need two for loops since Python supports "dynamic arrays":
def removeAndIndexPunctuation(word):
punctuations = []
# Index punctuation
for i, char in enumerate(word):
if char in string.punctuation:
punctuations.append((char, i))
# Remove all punctuation from word string
word = word.encode("utf-8").translate(None, string.punctuation).decode("utf-8")
return word, punctuations
So I just want to make sure, in this case in golang, do I absolutely need two for loops because it doesn't support dynamic arrays or am I missing something? Or in other words, If I'm looping over a set of characters and adding some to an array/slice, do I really need two loops, one for counting the number of characters for setting the length of the slice, and one for populating the slice?
I come from Python and am learning Go.
答案1
得分: 3
你不需要这样做。Golang的切片是动态数组(不要将它们与实际的数组混淆)。你应该(重新)阅读关于它的优秀的golang切片内部原理博文。
以下是用更符合惯用方式重写的示例:
func removeAndIndexPunctuation(word string) (string, []rune, []int) {
var punctuations []rune
var indexes []int
for i, char := range word {
if unicode.IsPunct(char) {
punctuations = append(punctuations, char)
indexes = append(indexes, i)
}
}
// 从单词字符串中删除所有标点符号
res := r.ReplaceAllString(word, "")
return res, punctuations, indexes
}
请注意,我认为在这里使用regex
并不特别相关。以下是使用切片的另一个版本:
func removeAndIndexPunctuation(word string) (string, []rune, []int) {
var punctuations []rune
var indexes []int
var result []rune
for i, char := range word {
if unicode.IsPunct(char) {
punctuations = append(punctuations, char)
indexes = append(indexes, i)
} else {
result = append(result, char)
}
}
return string(result), punctuations, indexes
}
英文:
You don't. Golang slices are dynamic arrays (don't confuse them for the actual arrays). You should (re-)read the excellent golang slice internals blog post about it.
Here is your example rewritten in a more idiomatic way:
func removeAndIndexPunctuation(word string) (string, []rune, []int) {
var punctuations []rune
var indexes []int
for i, char := range word {
if unicode.IsPunct(char) {
punctuations = append(punctuations, char)
indexes = append(indexes, i)
}
}
// Remove all punctuation from word string
res := r.ReplaceAllString(word, "")
return res, punctuations, indexes
}
Note that I don't think the use of regex
is particularly relevant here. Here is another version using a slice of runes:
func removeAndIndexPunctuation(word string) (string, []rune, []int) {
var punctuations []rune
var indexes []int
var result []rune
for i, char := range word {
if unicode.IsPunct(char) {
punctuations = append(punctuations, char)
indexes = append(indexes, i)
} else {
result = append(result, char)
}
}
return string(result), punctuations, indexes
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论