Jak uzyskać liczbę znaków ciągu w Go?
Na przykład, jeśli mam ciąg, "hello"
metoda powinna zwrócić 5
. Widziałem, że len(str)
zwraca liczbę bajtów, a nie liczbę znaków, więc len("£")
zwraca 2 zamiast 1, ponieważ £ jest kodowane za pomocą dwóch bajtów w UTF-8.
string
go
character
string-length
Ammar
źródło
źródło
Odpowiedzi:
Możesz spróbować
RuneCountInString
z pakietu utf8.że, jak zilustrowano w tym skrypcie : długość „Świata” może wynosić 6 (po chińsku: „世界”), ale liczba jego run to 2:
Phrozen dodaje w komentarzach :
Właściwie możesz zrobić
len()
nad runami, po prostu rzucając typ.len([]rune("世界"))
wydrukuje2
. Co najmniej w Go 1.3.A z CL 108985 (maj 2018, dla Go 1.11),
len([]rune(string))
jest teraz zoptymalizowany. (Rozwiązuje problem 24923 )Kompilator
len([]rune(string))
automatycznie wykrywa wzorzec i zastępuje go wywołaniem for r: = range s.Stefan Steiger wskazuje na post na blogu „ Normalizacja tekstu w Go ”
Co to jest postać?
Używając tego pakietu i jego
Iter
typu , rzeczywista liczba „znaków” byłaby następująca:Tutaj używa się formularza normalizacji Unicode NFKD „Dekompozycja zgodności”
Oliver „s odpowiedź wskazuje na UNICODE TEKSTU SEGMENTACJI jako jedyny sposób, aby niezawodnie wyznaczania granic pomiędzy niektórymi domyślne istotnych elementów tekstowych: odczuwanego przez użytkownika znaków, wyrazów i zdań.
W tym celu potrzebujesz zewnętrznej biblioteki, takiej jak rivo / uniseg , która obsługuje segmentację tekstu Unicode .
W rzeczywistości liczy się „ klaster grafemów ”, w którym wiele punktów kodowych można połączyć w jeden znak postrzegany przez użytkownika.
Dwa grafemy, mimo że są trzy runy (punkty kodowe Unicode).
Możesz zobaczyć inne przykłady w „ Jak manipulować ciągami znaków w GO, aby je odwrócić? ”
👩🏾🦰 sam to jeden grafem, ale od konwertera Unicode do punktów kodowych 4 runy:
źródło
Istnieje sposób, aby uzyskać liczbę run bez żadnych pakietów, konwertując ciąg na [] run jako
len([]rune(YOUR_STRING))
:źródło
Wiele zależy od twojej definicji tego, czym jest „postać”. Jeśli „runa równa się postaci” jest w porządku dla twojego zadania (generalnie tak nie jest), to odpowiedź VonC jest dla ciebie idealna. W przeciwnym razie należy prawdopodobnie zauważyć, że jest kilka sytuacji, w których liczba run w łańcuchu Unicode jest interesującą wartością. I nawet w takich sytuacjach lepiej, jeśli to możliwe, wywnioskować liczbę podczas „przechodzenia” przez ciąg, gdy runy są przetwarzane, aby uniknąć podwojenia wysiłku dekodowania UTF-8.
źródło
String
„s.length()
metoda nie zwraca liczbę znaków albo. Ani nie CocoaNSString
jest-length
metoda. Te po prostu zwracają liczbę jednostek UTF-16. Jednak prawdziwa liczba punktów kodowych jest rzadko używana, ponieważ jej policzenie wymaga czasu liniowego.Jeśli musisz wziąć pod uwagę klastry grafemów, użyj modułu regexp lub unicode. Zliczanie liczby punktów kodowych (run) lub bajtów jest również potrzebne do walidacji, ponieważ długość klastra grafemowego jest nieograniczona. Jeśli chcesz wyeliminować bardzo długie sekwencje, sprawdź, czy sekwencje są zgodne z formatem tekstu bezpiecznym dla strumienia .
źródło
var
poza funkcjami.Istnieje kilka sposobów uzyskania długości łańcucha:
źródło
Powinienem zwrócić uwagę, że żadna z dotychczas udzielonych odpowiedzi nie daje takiej liczby znaków, jakiej można się spodziewać, zwłaszcza gdy masz do czynienia z emoji (ale także z niektórymi językami, takimi jak tajski, koreański czy arabski). Sugestie VonC spowodują, że:
Dzieje się tak, ponieważ te metody liczą tylko punkty kodowe Unicode. Istnieje wiele znaków, które mogą składać się z wielu punktów kodowych.
To samo dotyczy korzystania z pakietu normalizacyjnego :
Normalizacja to tak naprawdę nie to samo, co liczenie znaków, a wielu znaków nie można znormalizować do odpowiednika jednego punktu kodowego.
odpowiedź masakielastic jest bliska, ale obsługuje tylko modyfikatory (flaga tęczowa zawiera modyfikator, który w związku z tym nie jest liczony jako własny punkt kodowy):
Prawidłowy sposób dzielenia łańcuchów Unicode na (postrzegane przez użytkownika) znaki, tj. Klastry grafemów, jest zdefiniowany w Załączniku nr 29 do Standardu Unicode . Zasady można znaleźć w sekcji 3.1.1 . W github.com/rivo/uniseg wdraża pakiet tych przepisów, tak można określić prawidłową liczbę znaków w ciągu:
źródło
Próbowałem zrobić normalizację trochę szybciej:
źródło