2016-05-28 20 views
5

Я предлагаю HackerRank попробовать, где проблемы часто требуют считывания строк целых чисел в массивы (фрагменты).Краткий и надежный способ чтения строки целых чисел, разделенных пробелами, в Go

Для многих проблем мой код анализа заканчивается большим, чем алгоритмическое мясо решения. Например, это было так в Sherlock and Array

Любые идеи о том, как кратко разделить строку целых чисел, разделенных пробелом, на срез? fmt.Scanf не поддерживает срезы и при использовании bufio Я получаю длинные решения.

Некоторые требования:

  • Вы можете использовать только стандартную библиотеку.
  • Решение должно быть кратким, чем короче, тем лучше.
  • Проверка ошибок не должна быть пропущена. Я знаю, что вход хорошо определен в HackerRank, и вы должны иметь возможность разрезать углы, но, пожалуйста, не делайте этого, это плохая практика.
  • Должно быть достаточно эффективно.

Примечание: Анализатор должен потреблять только одну строку, а не полный ввод.

ответ

1

1) прочитать строку

2) и добавьте в начале [ добавить ]

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) 
} 

также с использованием сплит строки (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: просто обнаружили, что числа, разделенных пробелом. Таким образом, этот код должен сделать вещь:

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) 
} 
+1

Хороший _abuse_ из JSON :) Тем не менее, строки разделенных пробелами (не разделенный запятыми) и читать полную линию довольно неэффективно в пространстве. – fons

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 
} 
+0

Я бы не назвал это кратким, на самом деле он похож на то, что я написал. – fons

+1

./shrug, если вы хотите крошечные функции, попробуйте ruby ​​:) – Plato

+0

Или Python, или Haskell :) Я бы хотел использовать go, но это заставляет тратить больше времени на парсинг-часть, чем на мясо проблемы. – fons

2

Вы можете использовать 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} 
+0

Это лучший вариант. Вам не нужно проверять наличие n, так как вы всегда будете получать ошибку, если n! = 1 – fons

+0

На самом деле, я остаюсь исправленным, это не работает, потому что оно не говорит об отдельных EOL и EOF, оно должно потреблять только строку , – fons

+0

Вы хотели бы отрисовать пробел ** в строке ** целых чисел в slice_. – noisypixy

0

Я использовал это в те времена, играя в 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 
} 
3

Ну, у меня есть также сделали некоторые проблемы хакерранка, и вот что я придумал. Как правило, проблемы начинаются с числом элементов в массиве:

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 
} 
Смежные вопросы