Puedes probar RuneCountInString
desde el paquete utf8.
devuelve el número de runas en p
que, como se ilustra en este script : la longitud de "Mundo" podría ser 6 (cuando se escribe en chino: "世界"), pero su número de runas es 2:
package main
import "fmt"
import "unicode/utf8"
func main() {
fmt.Println("Hello, 世界", len("世界"), utf8.RuneCountInString("世界"))
}
Phrozen agrega en los comentarios :
En realidad, puedes len()
superar las runas con solo escribir casting.
len([]rune("世界"))
imprimirá 2
. Al menos en Go 1.3.
Y con CL 108985 (mayo de 2018, para Go 1.11), len([]rune(string))
ahora está optimizado. ( Soluciona el problema 24923 )
El compilador detecta el len([]rune(string))
patrón automáticamente y lo reemplaza por r: = llamada de rango.
Agrega una nueva función de tiempo de ejecución para contar runas en una cadena. Modifica el compilador para detectar el patrón len([]rune(string))
y lo reemplaza con la nueva función de tiempo de ejecución de conteo de runas.
RuneCount/lenruneslice/ASCII 27.8ns ± 2% 14.5ns ± 3% -47.70% (p=0.000 n=10+10)
RuneCount/lenruneslice/Japanese 126ns ± 2% 60ns ± 2% -52.03% (p=0.000 n=10+10)
RuneCount/lenruneslice/MixedLength 104ns ± 2% 50ns ± 1% -51.71% (p=0.000 n=10+9)
Stefan Steiger señala la publicación del blog " Normalización de texto en Go "
¿Qué es un personaje?
Como se mencionó en la publicación del blog de cadenas , los personajes pueden abarcar múltiples runas .
Por ejemplo, un ' e
' y '◌́◌́' (agudo "\ u0301") pueden combinarse para formar 'é' (" e\u0301
" en NFD). Juntas, estas dos runas son un solo personaje .
La definición de un personaje puede variar según la aplicación.
Para la normalización lo definiremos como:
- una secuencia de runas que comienza con un iniciador,
- una runa que no se modifica ni combina hacia atrás con ninguna otra runa,
- seguido de una secuencia posiblemente vacía de no iniciadores, es decir, runas que lo hacen (típicamente acentos).
El algoritmo de normalización procesa un carácter a la vez.
Usando ese paquete y su Iter
tipo , el número real de "carácter" sería:
package main
import "fmt"
import "golang.org/x/text/unicode/norm"
func main() {
var ia norm.Iter
ia.InitString(norm.NFKD, "école")
nc := 0
for !ia.Done() {
nc = nc + 1
ia.Next()
}
fmt.Printf("Number of chars: %d\n", nc)
}
Aquí, esto usa el formulario de normalización Unicode NFKD "Descomposición de compatibilidad"
La respuesta de Oliver apunta a la SEGMENTACIÓN DE TEXTO UNICODE como la única forma de determinar de manera confiable los límites predeterminados entre ciertos elementos de texto significativos: caracteres percibidos por el usuario, palabras y oraciones.
Para eso, necesita una biblioteca externa como rivo / uniseg , que realiza la segmentación de texto Unicode .
Eso contará realmente " grupo de grafemas ", donde se pueden combinar múltiples puntos de código en un carácter percibido por el usuario.
package uniseg
import (
"fmt"
"github.com/rivo/uniseg"
)
func main() {
gr := uniseg.NewGraphemes("👍🏼!")
for gr.Next() {
fmt.Printf("%x ", gr.Runes())
}
// Output: [1f44d 1f3fc] [21]
}
Dos grafemas, aunque hay tres runas (puntos de código Unicode).
Puede ver otros ejemplos en " ¿Cómo manipular cadenas en GO para revertirlas? "
👩🏾🦰 solo es un grafema, pero, de unicode a convertidor de puntos de código , 4 runas: