在Go中读取一行空格分隔整数的简洁而强大的方法

时间:2022-10-08 03:33:20

I have been giving HackerRank a try where the problems often require reading lines of integers into arrays (slices).

我一直在尝试HackerRank,其中问题通常需要读取整数行(切片)。

For many of the problems, my parsing code ends up being larger than the algorithmic meat of the solution. For instance, that was the case in Sherlock and Array

对于许多问题,我的解析代码最终比解决方案的算法更大。例如,Sherlock和Array就是这种情况

Any ideas on how to concisely parse a space-separated line of integers into a slice? fmt.Scanf doesn't support slices and when using bufio I get long solutions.

关于如何简洁地将空格分隔的整数行解析成切片的任何想法? fmt.Scanf不支持切片,使用bufio时,我得到了很长的解决方案。

Some requirements:

  • You can only use the standard library.
  • 您只能使用标准库。

  • The solution should be concise, the shorter the better.
  • 解决方案应该简洁,越短越好。

  • Error checks shouldn't be skipped. I know that the input is well defined in HackerRank and you should be able to cut corners, but please don't, it's bad practice.
  • 不应跳过错误检查。我知道在HackerRank中输入是很明确的,你应该能够偷工减料,但请不要,这是不好的做法。

  • It should be reasonably efficient.
  • 它应该是合理有效的。

NOTE: The parser should only consume a single line and not the full input.

注意:解析器应该只使用一行而不是完整的输入。

5 个解决方案

#1


4  

Well, I have done some hackerrank problems too, and here is what I came up with. Typically, problems start with the number of items in the array:

好吧,我也做了一些黑客问题,这就是我想出来的。通常,问题始于数组中的项目数:

func main() {
    var N int
    fmt.Scanf("%d", &N)
    line := make([]int, N)
    for i, _ := range line {
        fmt.Scanf("%d", &line[i])
    }

    // Do something with the values
}

#2


2  

You can use fmt.Scanf, but you need to keep track of the values you're getting.

您可以使用fmt.Scanf,但需要跟踪所获得的值。

// a.go
package main

import (
    "fmt"
    "io"
)

func main() {
    var (
        next int
        nums []int
    )

    for {
        n, err := fmt.Scanf("%d", &next)
        if err == io.EOF {
            break
        }
        if err != nil {
            panic(err)
        }
        if n == 0 {
            break
        }

        nums = append(nums, next)
    }

    fmt.Printf("%#v\n", nums)
}

$ echo "4 8 15 16 23 42" | go run a.go
[]int{4, 8, 15, 16, 23, 42}

#3


1  

// inputs space separated list of integers, outputs []int64
package main

import (
    "bufio"
    "fmt"
    "strconv"
    "strings"
)

func main() {
    fmt.Println(parse("100 200 300"))
}

func parse(i string) (o []int64) {
    // from https://golang.org/pkg/bufio/#example_Scanner_custom
    s := bufio.NewScanner(strings.NewReader(i))
    splitter := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
        advance, token, err = bufio.ScanWords(data, atEOF)
        if err == nil && token != nil {
            x, err := strconv.ParseInt(string(token), 10, 32)
            if err != nil {
                panic(err)
            }
            o = append(o, x)
        }
        return
    }
    s.Split(splitter)
    for s.Scan() {
    }
    return o
}

#4


1  

1) read string

1)读取字符串

2) prepend [ and append ]

2)prepend [和追加]

3) parse as json into []int?

3)解析为json到[] int?

var input = "1,2,3"
var answer []int
j := []byte(fmt.Sprintf("[%s]",input))
err:= json.Unmarshal(j, &input)
if err != nil {
  panic(err)
}
for k,v := range input {
   fmt.Printf("Element №%v is %v\n", k,v)
}

also using split strings (https://godoc.org/strings#Split) and https://godoc.org/strconv#ParseInt

也使用拆分字符串(https://godoc.org/strings#Split)和https://godoc.org/strconv#ParseInt

input:= "1,2,3"
temp := strings.Split(input, ",")
var answer []int

for _,v := range temp {
  i,err := strconv.ParseInt(v)
  if err != nill {
     panic(err)
  }
  answer = append(answer, i)
}

UPD: just found that the numbers are SPACE separated. So, this code have to do the thing:

UPD:刚刚发现这些数字是SPACE分开的。所以,这段代码必须做的事情:

input:= "1 2 3"
temp := strings.Split(input, " ")
var answer []int

for _,v := range temp {
  i,err := strconv.ParseInt(v)
  if err != nill {
     panic(err)
  }
  answer = append(answer, i)
}

#5


0  

I've used this for those times playing in hackerrank (so concise, but not tested for humans):

我曾经在hackerrank玩这个时候(这么简洁,但没有为人类测试过):

func scanInt(n int) []int {
    input := make([]int, n)
    buffer := make([]interface{}, n)

    for i := 0; i < n; i++ {
        buffer[i] = &input[i]
    }

    fmt.Scanln(buffer...)

    return input
}

#1


4  

Well, I have done some hackerrank problems too, and here is what I came up with. Typically, problems start with the number of items in the array:

好吧,我也做了一些黑客问题,这就是我想出来的。通常,问题始于数组中的项目数:

func main() {
    var N int
    fmt.Scanf("%d", &N)
    line := make([]int, N)
    for i, _ := range line {
        fmt.Scanf("%d", &line[i])
    }

    // Do something with the values
}

#2


2  

You can use fmt.Scanf, but you need to keep track of the values you're getting.

您可以使用fmt.Scanf,但需要跟踪所获得的值。

// a.go
package main

import (
    "fmt"
    "io"
)

func main() {
    var (
        next int
        nums []int
    )

    for {
        n, err := fmt.Scanf("%d", &next)
        if err == io.EOF {
            break
        }
        if err != nil {
            panic(err)
        }
        if n == 0 {
            break
        }

        nums = append(nums, next)
    }

    fmt.Printf("%#v\n", nums)
}

$ echo "4 8 15 16 23 42" | go run a.go
[]int{4, 8, 15, 16, 23, 42}

#3


1  

// inputs space separated list of integers, outputs []int64
package main

import (
    "bufio"
    "fmt"
    "strconv"
    "strings"
)

func main() {
    fmt.Println(parse("100 200 300"))
}

func parse(i string) (o []int64) {
    // from https://golang.org/pkg/bufio/#example_Scanner_custom
    s := bufio.NewScanner(strings.NewReader(i))
    splitter := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
        advance, token, err = bufio.ScanWords(data, atEOF)
        if err == nil && token != nil {
            x, err := strconv.ParseInt(string(token), 10, 32)
            if err != nil {
                panic(err)
            }
            o = append(o, x)
        }
        return
    }
    s.Split(splitter)
    for s.Scan() {
    }
    return o
}

#4


1  

1) read string

1)读取字符串

2) prepend [ and append ]

2)prepend [和追加]

3) parse as json into []int?

3)解析为json到[] int?

var input = "1,2,3"
var answer []int
j := []byte(fmt.Sprintf("[%s]",input))
err:= json.Unmarshal(j, &input)
if err != nil {
  panic(err)
}
for k,v := range input {
   fmt.Printf("Element №%v is %v\n", k,v)
}

also using split strings (https://godoc.org/strings#Split) and https://godoc.org/strconv#ParseInt

也使用拆分字符串(https://godoc.org/strings#Split)和https://godoc.org/strconv#ParseInt

input:= "1,2,3"
temp := strings.Split(input, ",")
var answer []int

for _,v := range temp {
  i,err := strconv.ParseInt(v)
  if err != nill {
     panic(err)
  }
  answer = append(answer, i)
}

UPD: just found that the numbers are SPACE separated. So, this code have to do the thing:

UPD:刚刚发现这些数字是SPACE分开的。所以,这段代码必须做的事情:

input:= "1 2 3"
temp := strings.Split(input, " ")
var answer []int

for _,v := range temp {
  i,err := strconv.ParseInt(v)
  if err != nill {
     panic(err)
  }
  answer = append(answer, i)
}

#5


0  

I've used this for those times playing in hackerrank (so concise, but not tested for humans):

我曾经在hackerrank玩这个时候(这么简洁,但没有为人类测试过):

func scanInt(n int) []int {
    input := make([]int, n)
    buffer := make([]interface{}, n)

    for i := 0; i < n; i++ {
        buffer[i] = &input[i]
    }

    fmt.Scanln(buffer...)

    return input
}