英文:
loop through slices and amend into a 2D array
问题
我有17个索引片段(len(inputStartSlice)
),它们将生成一系列字符串片段。目前,我的代码只能生成一个字符串片段(一个输入),因为我在硬编码位置时只能生成一个。但我需要循环遍历这17个索引片段,将它们组合成一个二维字符串数组。
var inputSlices []string
var inputStartSlice []int
var inputEndSlice []int
var input []string
var inputs [][]string
for v, line := range inputSlices {
if strings.Contains(line, "{") {
inputStartSlice = append(inputStartSlice, v)
}
if strings.Contains(line, "}") {
inputEndSlice = append(inputEndSlice, v+1)
}
}
input = inputSlice[inputStartSlice[3]:inputEndSlice[3]]
inputs = append(inputs, input)
fmt.Println(inputs)
有没有更好的方法来解决这个问题?我相信有,如果有人能帮我理解更好的方法或详细说明我目前遇到的问题,那就太好了。
英文:
I have 17 (len(inputStartSlice)
) slices of indexes that'll make a series of string slices. Currently, my code is only producing a single slice of strings (a single input, as I hardcode the positions, seen below) when I have 17 that I need to loop through into a single, 2D array of strings.
var inputSlices []string
var inputStartSlice []int
var inputEndSlice []int
var input []string
var inputs [][]string
for v, line := range inputSlices {
if strings.Contains(line, "{") {
inputStartSlice = append(inputStartSlice, v)
}
if strings.Contains(line, "}") {
inputEndSlice = append(inputEndSlice, v+1)
}
}
input = inputSlice[inputStartSlice[3]:inputEndSlice[3]]
inputs = append(inputs, input)
fmt.Println(inouts)
Is there a better way to go about doing this? I'm sure there is, if anybody can help me understand better approaches or elaborate on how I can solve where I'm currently stuck..
答案1
得分: 1
我已经用更符合惯用方式的方式重写了你的代码。请查看注释以了解解释。这段代码是可行的,但正如 mpx 建议的那样,为了处理任何自定义格式,你需要编写一个分词器和一个词法分析器,以确保一切都被正确解析,并处理每个可能的语法错误。
package main
import (
"fmt"
"log"
"strings"
"golang.org/x/exp/slices"
)
func main() {
var codeSlices = []string{
"# INPUTS",
"",
"input CreateUserInput {",
" username: String!",
" email: String!",
" password: String!",
"}",
"",
"input AuthUserInput {",
" user: String!",
" password: String!",
" code: String",
"}",
"",
"input RefreshTokensInput{",
" refreshToken: String!",
"}",
"",
"input VerifyEmailInput {",
" token: String!",
"}",
"",
"# OBJECTS",
"",
}
// 检查边界
inputStart := slices.Index(codeSlices, "# INPUTS") // 使用内置函数进行搜索
if inputStart == -1 {
log.Fatal("# INPUTS 未找到")
}
objectStart := slices.Index(codeSlices, "# OBJECTS")
if objectStart == -1 {
log.Fatal("# OBJECTS 未找到")
}
var inputStartSlice []int
var inputEndSlice []int
// 无需将 codeSlices 复制到 inputSlice,直接从 inputs 到 objects,这样更快。
for i := inputStart + 2; i < objectStart-1; i++ {
if strings.HasSuffix(codeSlices[i], "{") { // HasSuffix 更适合这里,因为 { 必须是最后一个字符
inputStartSlice = append(inputStartSlice, i)
continue // 无需检查闭合括号,所以我们可以继续跳过另一个检查
}
if codeSlices[i] == "}" { // 直接相等比 Contains 更快
inputEndSlice = append(inputEndSlice, i+1)
}
}
// 检查每个开放括号是否有一个闭合括号
if len(inputStartSlice) != len(inputEndSlice) {
log.Fatal("len(inputStartSlice) != len(inputEndSlice)")
}
// 拼接最终结果
var inputs [][]string
for i := range inputStartSlice {
inputs = append(inputs, codeSlices[inputStartSlice[i]:inputEndSlice[i]])
}
fmt.Println(inputs)
}
英文:
I've rewritten your code in a more idiomatic way. Check the comments for explanations. This code works, but as mpx suggested, for processing any custom format you have to write a tokenizer and a lexer to be sure that everything is parsed correctly and every possible syntax error is handled.
package main
import (
"fmt"
"log"
"strings"
"golang.org/x/exp/slices"
)
func main() {
var codeSlices = []string{
"# INPUTS",
"",
"input CreateUserInput {",
" username: String!",
" email: String!",
" password: String!",
"}",
"",
"input AuthUserInput {",
" user: String!",
" password: String!",
" code: String",
"}",
"",
"input RefreshTokensInput{",
" refreshToken: String!",
"}",
"",
"input VerifyEmailInput {",
" token: String!",
"}",
"",
"# OBJECTS",
"",
}
//Check for boundaries
inputStart := slices.Index(codeSlices, "# INPUTS") //Use built-in functions for the search
if inputStart == -1 {
log.Fatal("# INPUTS not found")
}
objectStart := slices.Index(codeSlices, "# OBJECTS")
if objectStart == -1 {
log.Fatal("# OBJECTS not found")
}
var inputStartSlice []int
var inputEndSlice []int
//No need to copy your codeSlices to inputSlice, just go from inputs to objects, this is faster.
for i := inputStart + 2; i < objectStart-1; i++ {
if strings.HasSuffix(codeSlices[i], "{") { //HasSuffix is better here, since the { must be the last char
inputStartSlice = append(inputStartSlice, i)
continue //No need to check for closing bracket, so we can continue to skip another check
}
if codeSlices[i] == "}" { //Direct equality is faster than Contains
inputEndSlice = append(inputEndSlice, i+1)
}
}
//Check to every open bracket have a closing one
if len(inputStartSlice) != len(inputEndSlice) {
log.Fatal("len(inputStartSlice) != len(inputEndSlice)")
}
//Concating final results
var inputs [][]string
for i := range inputStartSlice {
inputs = append(inputs, codeSlices[inputStartSlice[i]:inputEndSlice[i]])
}
fmt.Println(inputs)
}
答案2
得分: 1
你可以在不使用额外变量的情况下实现相同的效果。
package main
import (
"fmt"
"log"
"strings"
"golang.org/x/exp/slices"
)
func main() {
var codeSlices = []string{
"# INPUTS",
"",
"input CreateUserInput {",
" username: String!",
" email: String!",
" password: String!",
"}",
"",
"input AuthUserInput {",
" user: String!",
" password: String!",
" code: String",
"}",
"",
"input RefreshTokensInput{",
" refreshToken: String!",
"}",
"",
"input VerifyEmailInput {",
" token: String!",
"}",
"",
"# OBJECTS",
"",
}
// 检查边界
inputStart := slices.Index(codeSlices, "# INPUTS") // 使用内置函数进行搜索
if inputStart == -1 {
log.Fatal("# INPUTS 未找到")
}
objectStart := slices.Index(codeSlices, "# OBJECTS")
if objectStart == -1 {
log.Fatal("# OBJECTS 未找到")
}
inputStart = 0
var inputs [][]string
for i := inputStart + 2; i < objectStart-1; i++ {
if idx := strings.Index(codeSlices[i], "{"); idx > 0 {
inputStart = i
continue
}
if idx := slices.Index(codeSlices[inputStart:], "}"); inputStart > 0 {
inputs = append(inputs, codeSlices[inputStart:i+idx])
inputStart = 0
}
}
if inputStart > 0 {
log.Fatal("输入不匹配")
}
fmt.Printf("%#v\n", inputs)
}
英文:
You can achieve the same without using extra variables
package main
import (
"fmt"
"log"
"strings"
"golang.org/x/exp/slices"
)
func main() {
var codeSlices = []string{
"# INPUTS",
"",
"input CreateUserInput {",
" username: String!",
" email: String!",
" password: String!",
"}",
"",
"input AuthUserInput {",
" user: String!",
" password: String!",
" code: String",
"}",
"",
"input RefreshTokensInput{",
" refreshToken: String!",
"}",
"",
"input VerifyEmailInput {",
" token: String!",
"}",
"",
"# OBJECTS",
"",
}
//Check for boundaries
inputStart := slices.Index(codeSlices, "# INPUTS") //Use built-in functions for the search
if inputStart == -1 {
log.Fatal("# INPUTS not found")
}
objectStart := slices.Index(codeSlices, "# OBJECTS")
if objectStart == -1 {
log.Fatal("# OBJECTS not found")
}
inputStart = 0
var inputs [][]string
for i := inputStart + 2; i < objectStart-1; i++ {
if idx := strings.Index(codeSlices[i], "{"); idx > 0 {
inputStart = i
continue
}
if idx := slices.Index(codeSlices[inputStart:], "}"); inputStart > 0 {
inputs = append(inputs, codeSlices[inputStart:i+idx])
inputStart = 0
}
}
if inputStart > 0 {
log.Fatal("Mismatch inputs")
}
fmt.Printf("%#v\n", inputs)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论