循环遍历切片并将其添加到一个二维数组中。

huangapple go评论75阅读模式
英文:

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)

Playground

有没有更好的方法来解决这个问题?我相信有,如果有人能帮我理解更好的方法或详细说明我目前遇到的问题,那就太好了。

英文:

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)

Playground

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 (
&quot;fmt&quot;
&quot;log&quot;
&quot;strings&quot;
&quot;golang.org/x/exp/slices&quot;
)
func main() {
var codeSlices = []string{
&quot;# INPUTS&quot;,
&quot;&quot;,
&quot;input CreateUserInput {&quot;,
&quot;  username: String!&quot;,
&quot;  email: String!&quot;,
&quot;  password: String!&quot;,
&quot;}&quot;,
&quot;&quot;,
&quot;input AuthUserInput {&quot;,
&quot;  user: String!&quot;,
&quot;  password: String!&quot;,
&quot;  code: String&quot;,
&quot;}&quot;,
&quot;&quot;,
&quot;input RefreshTokensInput{&quot;,
&quot;  refreshToken: String!&quot;,
&quot;}&quot;,
&quot;&quot;,
&quot;input VerifyEmailInput {&quot;,
&quot;  token: String!&quot;,
&quot;}&quot;,
&quot;&quot;,
&quot;# OBJECTS&quot;,
&quot;&quot;,
}
//Check for boundaries
inputStart := slices.Index(codeSlices, &quot;# INPUTS&quot;) //Use built-in functions for the search
if inputStart == -1 {
log.Fatal(&quot;# INPUTS not found&quot;)
}
objectStart := slices.Index(codeSlices, &quot;# OBJECTS&quot;)
if objectStart == -1 {
log.Fatal(&quot;# OBJECTS not found&quot;)
}
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 &lt; objectStart-1; i++ {
if strings.HasSuffix(codeSlices[i], &quot;{&quot;) { //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] == &quot;}&quot; { //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(&quot;len(inputStartSlice) != len(inputEndSlice)&quot;)
}
//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)
}

Playground

英文:

You can achieve the same without using extra variables

package main

import (
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;strings&quot;

	&quot;golang.org/x/exp/slices&quot;
)

func main() {

	var codeSlices = []string{
		&quot;# INPUTS&quot;,
		&quot;&quot;,
		&quot;input CreateUserInput {&quot;,
		&quot;  username: String!&quot;,
		&quot;  email: String!&quot;,
		&quot;  password: String!&quot;,
		&quot;}&quot;,
		&quot;&quot;,
		&quot;input AuthUserInput {&quot;,
		&quot;  user: String!&quot;,
		&quot;  password: String!&quot;,
		&quot;  code: String&quot;,
		&quot;}&quot;,
		&quot;&quot;,
		&quot;input RefreshTokensInput{&quot;,
		&quot;  refreshToken: String!&quot;,
		&quot;}&quot;,
		&quot;&quot;,
		&quot;input VerifyEmailInput {&quot;,
		&quot;  token: String!&quot;,
		&quot;}&quot;,
		&quot;&quot;,
		&quot;# OBJECTS&quot;,
		&quot;&quot;,
	}

	//Check for boundaries
	inputStart := slices.Index(codeSlices, &quot;# INPUTS&quot;) //Use built-in functions for the search
	if inputStart == -1 {
		log.Fatal(&quot;# INPUTS not found&quot;)
	}

	objectStart := slices.Index(codeSlices, &quot;# OBJECTS&quot;)
	if objectStart == -1 {
		log.Fatal(&quot;# OBJECTS not found&quot;)
	}

	inputStart = 0
	var inputs [][]string
	for i := inputStart + 2; i &lt; objectStart-1; i++ {
		if idx := strings.Index(codeSlices[i], &quot;{&quot;); idx &gt; 0 {
			inputStart = i
			continue
		}
		if idx := slices.Index(codeSlices[inputStart:], &quot;}&quot;); inputStart &gt; 0 {
			inputs = append(inputs, codeSlices[inputStart:i+idx])
			inputStart = 0
		}
	}

	if inputStart &gt; 0 {
		log.Fatal(&quot;Mismatch inputs&quot;)
	}

	fmt.Printf(&quot;%#v\n&quot;, inputs)
}

Playground

huangapple
  • 本文由 发表于 2022年5月4日 17:40:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/72110852.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定