英文:
Cleaner way to iterate through array + create a string from values
问题
使用这段代码,有没有更好的方法来遍历所有用户并创建一个包含他们所有Nick
值的新字符串?
package main
import "fmt"
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{Nick: "Radar"}
users[1] = User{Nick: "NotRadar"}
names := ":"
for _, u := range users {
names += u.Nick + " "
}
fmt.Println(names)
}
package main
import "fmt"
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{Nick: "Radar"}
users[1] = User{Nick: "NotRadar"}
names := ":"
for _, u := range users {
names += u.Nick + " "
}
fmt.Println(names)
}
英文:
With this code, is there a better way to loop through all the users and create a new string containing all their Nick
values?
package main
import "fmt"
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{ Nick: "Radar" }
users[1] = User{ Nick: "NotRadar" }
names := ":"
for _, u := range users {
names += u.Nick + " "
}
fmt.Println(names)
}
答案1
得分: 5
例如,
package main
import (
"bytes"
"fmt"
)
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{Nick: "Radar"}
users[1] = User{Nick: "NotRadar"}
var buf bytes.Buffer
buf.WriteByte(':')
for _, u := range users {
buf.WriteString(u.Nick)
buf.WriteByte(' ')
}
names := buf.String()
fmt.Println(names)
}
这样可以避免由于string
的连接而产生大量的分配。
你也可以这样写:
package main
import (
"fmt"
)
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{Nick: "Radar"}
users[1] = User{Nick: "NotRadar"}
var buf []byte
buf = append(buf, ':')
for _, u := range users {
buf = append(buf, u.Nick...)
buf = append(buf, ' ')
}
names := string(buf)
fmt.Println(names)
}
英文:
For example,
package main
import (
"bytes"
"fmt"
)
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{Nick: "Radar"}
users[1] = User{Nick: "NotRadar"}
var buf bytes.Buffer
buf.WriteByte(':')
for _, u := range users {
buf.WriteString(u.Nick)
buf.WriteByte(' ')
}
names := buf.String()
fmt.Println(names)
}
This avoids a lot of allocations due to the concatenation of string
s.
You could also write:
package main
import (
"fmt"
)
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{Nick: "Radar"}
users[1] = User{Nick: "NotRadar"}
var buf []byte
buf = append(buf, ':')
for _, u := range users {
buf = append(buf, u.Nick...)
buf = append(buf, ' ')
}
names := string(buf)
fmt.Println(names)
}
答案2
得分: 2
这里看起来你想要使用strings.Join。你可能想要避免原始代码中重复字符串连接的紧密循环;我相当确定Go语言没有为其原始字符串实现类似绳索的数据结构。
package main
import (
"fmt"
"strings"
)
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{Nick: "Radar"}
users[1] = User{Nick: "NotRadar"}
userNames := []string{}
for _, u := range users {
userNames = append(userNames, u.Nick)
}
names := ":" + strings.Join(userNames, " ")
fmt.Println(names)
}
英文:
It really looks like you want a strings.Join here. You probably want to avoid that tight loop of repeated string concatenations in the original code; I'm fairly certain that Go doesn't implement a rope-like data structure for its primitive strings.
package main
import (
"fmt"
"strings"
)
type User struct {
Nick string
}
func main() {
var users [2]User
users[0] = User{Nick: "Radar"}
users[1] = User{Nick: "NotRadar"}
userNames := []string{}
for _, u := range users {
userNames = append(userNames, u.Nick)
}
names := ":" + strings.Join(userNames, " ")
fmt.Println(names)
}
答案3
得分: 1
很不幸,我不知道有更优雅的方法来编写那段代码。
Go确实有一个String.Join方法,所以如果你创建一个将用户数组转换为字符串切片([]string
)的辅助函数,然后将其传递给String.Join
,就可以实现这个功能。
我认为Go的静态类型和缺乏模板使得编写一个像Ruby那样通用的map
函数变得困难。
英文:
Unfortunately, I do not know of a more elegant way to write that code.
Go does have a String.Join method so if you made a helper that converted your array of users to a slice of strings ([]string
) then you could pass that to String.Join
.
I think that Go's static typing and lack of templates makes it hard to write a general purpose map
function like Ruby has.
答案4
得分: 1
这是我在dyoo的帖子评论中谈论的内容。这实际上是对join的重写,以防止额外迭代列表并分配额外的切片。
func Usernames(users []User) string {
if len(users) == 0 {
return ""
}
if len(users) == 1 {
return users[0].Name
}
sep := " "
n := len(users)-1 // 从 len(sep) * len(a)-1,sep始终是长度为1,不像Join中那样
for i := 0; i < len(users); i++ {
n += len(users[i].Name)
}
names := make([]byte,n)
namesp := copy(names, users[0].Name)
for _,u := range users[1:] {
namesp += copy(names[namesp:], sep)
namesp += copy(names[namesp:], u.Name)
}
return string(names)
}
供参考,strings.go中的strings.Join源代码:
http://golang.org/src/pkg/strings/strings.go
请参考第356行。
英文:
This is what I was talking about in the comments of dyoo's post. Effectively a rewrite of join to prevent having to iterate over the list an extra time and allocate an extra slice.
func Usernames(users []User) string {
if len(users) == 0 {
return ""
}
if len(users) == 1 {
return users[0].Name
}
sep := " "
n := len(users)-1 // From len(sep) * len(a)-1, sep is always len 1 unlike in Join
for i := 0; i < len(users); i++ {
n += len(users[i].Name)
}
names := make([]byte,n)
namesp := copy(names, users[0].Name)
for _,u := range users[1:] {
namesp += copy(names[namesp:], sep)
namesp += copy(names[namesp:], u.Name)
}
return string(names)
}
For reference, strings.go with the strings.Join source:
http://golang.org/src/pkg/strings/strings.go
See line 356
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论