Analizar numerales de una cadena en Golang -- beginner campo con strings campo con go camp codereview Relacionados El problema

Parse Numerals from a String in Golang


4
vote

problema

Español

Hace poco probé mi mano en la escritura de IR CODE para un proyecto en el que estoy trabajando. Para poder ayudarme a obtener un mejor agarre, decidí escribir un programa simple pero algo práctico para analizar los caracteres de números de cadenas en función de los valores ASCII de las runas dentro, y las adjuntarlas a una rebanada.

Mis preocupaciones primarias con este código son:

  • puede que no sea una buena solución.
  • Puede que no sea muy actuador.
  • Puede que no sea muy idiomático o reflexivo de las mejores prácticas.
  • Puede que no sea muy conciso, limpio o legible.

NOTA: El código a continuación contiene los comentarios de la documentación. Dado que esta es mi primera vez usando el intercambio de pilas, no estoy completamente seguro de si esto es razonable o no es razonable y hace que la lectura sea un poco larga.

  /* parseNum package This is a package which contains a function for converting characters (charToInt), in the form of runes, into numerals. It also contains a function for parsing numerals from strings (parseNum). */ package main  import (     "errors"     "fmt" )  /* CharToNum function This is a function which recieves a rune and converts it to a numeral based on its ascii code by matching it against the numeral ascii codes in a for loop. It subtracts 48 from the code to get the actual numeral, as the ascii codes for numerals are 48-57 and simple subtraction gives you the actual numeral. */ func CharToNum(r rune) (int, error) {     for i := 48; i <= 57; i++ {         if int(r) == i {             return (int(r) - 48), nil         }     }     return -1, errors.New("type: rune was not int") }  /* ParseNum function This is a function which serves the purpose of identifying numerals inside strings and returning them in a slice. It loops over the string, passing each character to the charToNum function and identifying whether it should append the output to the array by testing whether or not the error evaluates to nil. */ func ParseNum(str string) []int {     var nums []int     for _, val := range str {         num, err := CharToNum(val)         if err != nil {             continue         }         nums = append(nums, num)     }     return nums }  func main() {     fmt.Println(ParseNum("000123456789000")) }   
Original en ingles

I recently tried my hand at writing Go code for a project I'm working on. In order to help myself get a better grasp I decided to write a simple yet somewhat practical program for parsing numeral characters from strings based on the ascii values of the runes within, and appending them to a slice.

My primary concerns with this code are:

  • It may not be a good solution.
  • It may not be very performant.
  • It may not be very idiomatic or reflective of best practices.
  • It may not be very concise, clean, or readable.

Note: The code below contains the documentation comments. Since this is my first time using Stack Exchange, I'm not entirely certain whether or not this is reasonable and it makes the read a little long.

/* parseNum package This is a package which contains a function for converting characters (charToInt), in the form of runes, into numerals. It also contains a function for parsing numerals from strings (parseNum). */ package main  import (     "errors"     "fmt" )  /* CharToNum function This is a function which recieves a rune and converts it to a numeral based on its ascii code by matching it against the numeral ascii codes in a for loop. It subtracts 48 from the code to get the actual numeral, as the ascii codes for numerals are 48-57 and simple subtraction gives you the actual numeral. */ func CharToNum(r rune) (int, error) {     for i := 48; i <= 57; i++ {         if int(r) == i {             return (int(r) - 48), nil         }     }     return -1, errors.New("type: rune was not int") }  /* ParseNum function This is a function which serves the purpose of identifying numerals inside strings and returning them in a slice. It loops over the string, passing each character to the charToNum function and identifying whether it should append the output to the array by testing whether or not the error evaluates to nil. */ func ParseNum(str string) []int {     var nums []int     for _, val := range str {         num, err := CharToNum(val)         if err != nil {             continue         }         nums = append(nums, num)     }     return nums }  func main() {     fmt.Println(ParseNum("000123456789000")) } 
        

Lista de respuestas

4
 
vote
vote
La mejor respuesta
 

En tu pregunta, escribiste:

  //5  

En su respuesta, Jano escribió:

  //6  

usando Idiomatic Go, escribo,

  //7  

Es simple y directo y es rápido. Benchmarking los números cero a las nueve:

  //8  

Benchmarking El espacio numérico no válido ( //9 ):

  from __future__ import division0  

La variable de error from __future__ import division1 Se puede usar para verificar un error específico, por ejemplo, from __future__ import division2 .


En tu pregunta, escribiste:

  from __future__ import division3  

usando Idiomatic Go, escribo,

  from __future__ import division4  

Minimiza tanto la hora de la CPU como las asignaciones de memoria; es rápido. Benchmarking la cadena from __future__ import division5 :

  from __future__ import division6  

Los caracteres Unicode y UTF-8 correspondientes al conjunto ASCII tienen los mismos valores de byte que ASCII.


Consulte puntos de referencia, pruebas de paquetes .

 

In your question, you wrote:

func CharToNum(r rune) (int, error) {     for i := 48; i <= 57; i++ {         if int(r) == i {             return (int(r) - 48), nil         }     }     return -1, errors.New("type: rune was not int") } 

In his answer, Janos wrote:

func CharToNum(r rune) (int, error) {     intval := int(r) - '0'     if 0 <= intval && intval <= 9 {         return intval, nil     }     return -1, errors.New("type: rune was not int") } 

Using idiomatic Go, I wrote,

var ErrRuneNotInt = errors.New("type: rune was not int")  func CharToNum(r rune) (int, error) {     if '0' <= r && r <= '9' {         return int(r) - '0', nil     }     return 0, ErrRuneNotInt } 

It's simple and direct and it's fast. Benchmarking the numbers zero through nine:

BenchmarkCharToNumTschfld    5000000    323 ns/op BenchmarkCharToNumPeter     50000000     37.7 ns/op 

Benchmarking the invalid numeric character space (' '):

BenchmarkCharToNumErrTschfld    10000000      242 ns/op       16 B/op      1 allocs/op BenchmarkCharToNumErrPeter      2000000000      1.26 ns/op     0 B/op      0 allocs/op 

The error variable ErrRuneNotInt can be used to check for a specific error, for example, if err == ErrRuneNotInt {}.


In your question, you wrote:

func ParseNum(str string) []int {     var nums []int     for _, val := range str {         num, err := CharToNum(val)         if err != nil {             continue         }         nums = append(nums, num)     }     return nums } 

Using idiomatic Go, I wrote,

func ParseNum(s string) []int {     nLen := 0     for i := 0; i < len(s); i++ {         if b := s[i]; '0' <= b && b <= '9' {             nLen++         }     }     var n = make([]int, 0, nLen)     for i := 0; i < len(s); i++ {         if b := s[i]; '0' <= b && b <= '9' {             n = append(n, int(b)-'0')         }     }     return n } 

It minimizes both CPU time and memory allocations; it's fast. Benchmarking the string "000123456789000":

BenchmarkParseNumTschfld     1000000    2475 ns/op     248 B/op    5 allocs/op BenchmarkParseNumPeter       2000000     610 ns/op     128 B/op    1 allocs/op 

Unicode and UTF-8 characters corresponding to the ASCII set have the same byte values as ASCII.


See Benchmarks, Package testing.

 
 
2
 
vote

en lugar de este bucle:

  for i := 48; i <= 57; i++ {     if int(r) == i {         return (int(r) - 48), nil     } }   

Esto es equivalente:

  intval := int(r) if 48 <= intval && intval <= 57 {     return (intval - 48), nil }   

y si subtamos 48 antes, el código comenzará a lucir más natural:

  intval := int(r) - 48 if 0 <= intval && intval <= 9 {     return intval, nil }   

¿Y qué es este mágico 48 realmente? El código ASCII de '0' ¡Por supuesto! Podemos escribirlo de esa manera:

  intval := int(r) - '0'   

El nombre ParseNum es un poco engañoso. Por ejemplo, una función llamada parseInt generalmente intenta convertir una cadena a un entero, y si la cadena no es un entero válido, aumenta un error. No es así como ParseNum funciona. ParseNum convertirá felizmente "he1l2l3oth4ere" a intval := int(r) if 48 <= intval && intval <= 57 { return (intval - 48), nil } 0 . Un nombre mejor sería intval := int(r) if 48 <= intval && intval <= 57 { return (intval - 48), nil } 1 o intval := int(r) if 48 <= intval && intval <= 57 { return (intval - 48), nil } 2 .

 

Instead of this loop:

for i := 48; i <= 57; i++ {     if int(r) == i {         return (int(r) - 48), nil     } } 

This is equivalent:

intval := int(r) if 48 <= intval && intval <= 57 {     return (intval - 48), nil } 

And if we subtract 48 earlier, the code will start to look more natural:

intval := int(r) - 48 if 0 <= intval && intval <= 9 {     return intval, nil } 

And what is this magical 48 really? The ASCII code of '0' of course! We can write it that way:

intval := int(r) - '0' 

The name ParseNum is a bit misleading. For example a function called parseInt usually tries to convert a string to an integer, and if the string is not a valid integer, it raises an error. That's not how ParseNum works. ParseNum will happily convert "he1l2l3oth4ere" to [1234]. A better name would be StripNonDigit or ExtractDigits.

 
 
   
   

Relacionados problema

7  Árboles binarios equivalentes (un recorrido por go)  ( Equivalent binary trees a tour of go ) 
Cualquier sugerencia sobre cómo mejorar el código que se muestra a continuación para la Ejercicio de go-tour ? < / p> Descripción del ejercicio: Puede ha...

1  Solicitar enrutador escrito en Go  ( Request router written in go ) 
Comencé a aprender Idioma y me imaginé escribir otro enrutador de solicitud, ya que lo necesito para mi próximo proyecto Go. Como es lo que es lo primero que ...

6  Implementando una API de descanso en Ir usando Gorilla / Mux y Gorm  ( Implementing a rest api in go using gorilla mux and gorm ) 
Mientras está aprendiendo, decidí implementar una API de descanso simple para conocer el idioma y, dado que estoy inexperto en el principio, apreciaría cualq...

12  Entrevista de concurrencia  ( Concurrency interview ) 
Un poco de vuelta, tuve una entrevista donde plantearon un problema, en resumen: Mire un determinado directorio, y procese archivos JSON entrantes Estos ...

1  Formateo de un archivo de texto cambia como HTML  ( Formatting a changes text file as html ) 
Tengo una función que se usa para convertir texto (un archivo de cambios) en HTML para leer. La función es esencialmente basada en línea: si la línea es de es...

7  Descarga concurrente en Go  ( Concurrent download in go ) 
Escribí un programa para descargar archivos en manera concurrente / paralelo (gomaxprocs & gt; 1). Este es mi programa 2 nd (no juguete) escrito en Go. Po...

5  Herramienta para calcular el tiempo promedio que toma para una solicitud de tracción GitHub para fusionar  ( Tool to calculate the average time that takes for a github pull request to get m ) 
Estoy aprendiendo, y este es mi primer intento de una herramienta de línea de comandos que usa la API de GitHub para calcular el tiempo promedio que toma una ...

4  Pasando alrededor del contexto.Context en Golang  ( Passing around context context in golang ) 
Actualmente soy "graciosamente" Manejar el servidor HTTP net/http Apagado que funciona perfectamente bien ( No le estoy pidiendo que revise el cierre del se...

2  Consulta Seleccione e inserte si no existe  ( Query select and insert if not exists ) 
¿Hay alguna buena manera de hacer este método más corto? "var text = document.getElementById('text'); var greeting = ['Hello. I am a console wannabe.', ...

3  Archivo de registro diferido Cerrar  ( Deferred log file close ) 
Mi código funciona en que se compila, y cuando se ejecuta, escribe un archivo de registro utilizando un escritor búfer. pero me pregunto si: Soy correcto...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos