سؤال

كيف يمكنني الحصول على عدد أحرف السلسلة في Go؟

على سبيل المثال، إذا كان لدي سلسلة "hello" يجب أن تعود الطريقة 5.رأيت ذلك len(str) إرجاع عدد البايتات و لا عدد الأحرف ذلك len("£") تُرجع 2 بدلاً من 1 لأن £ يتم ترميزه بوحدتي بايت في UTF-8.

هل كانت مفيدة؟

المحلول

يمكنك محاولة RuneCountInString من utf8 الحزمة.

إرجاع عدد الأحرف الرونية في p

ذلك ، كما هو موضح في هذا البرنامج النصي:طول "العالم" قد تكون 6 (عندما كتب في الصينية:"世界") ، ولكن رون عدد 2:

package main

import "fmt"
import "unicode/utf8"

func main() {
    fmt.Println("Hello, 世界", len("世界"), utf8.RuneCountInString("世界"))
}

Phrozen يضيف في التعليقات:

في الواقع يمكنك أن تفعل len() أكثر من اساطير فقط نوع الصب.
len([]rune("世界")) طباعة 2.في leats في الذهاب 1.3.


و مع CL 108985 (أيار / مايو 2018 ، تذهب 1.11), len([]rune(string)) هو الأمثل الآن.(إصلاحات المسألة 24923)

مترجم بالكشف عن len([]rune(string)) نمط تلقائيا ، ويستبدلها مع r := مجموعة s الاتصال.

يضيف جديد runtime وظيفة العد اساطير في سلسلة.يعدل مترجم للكشف عن نمط len([]rune(string)) ويستبدلها مع رون عد تشغيل وظيفة.

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)

ستيفان ستيغر يشير إلى بلوق وظيفة "النص التطبيع في الذهاب"

ما هي الشخصية ؟

كما ذكر في سلاسل بلوق وظيفة, شخصيات يمكن أن تمتد عدة اساطير.
على سبيل المثال ، e'و '◌◌' (الحادة "\u0301") يمكن الجمع بين لتشكيل 'é' ("e\u0301"في NFD). معا هذه اثنين الرونية هي حرف واحد.

تعريف شخصية قد تختلف اعتمادا على التطبيق.
بالنسبة التطبيع وسوف تعرف على أنها:

  • سلسلة من الأحرف الرونية التي تبدأ مع بداية ،
  • رون أنه لا تعديل أو الجمع إلى الوراء مع أي رون ،
  • تليها ربما فارغة تسلسل غير للمبتدئين, وهذا هو ، الرونية التي (عادة لهجات).

تطبيع خوارزمية عمليات حرف واحد في ذلك الوقت.

باستخدام هذه الحزمة و Iter نوع, العدد الفعلي "حرف" سيكون:

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

هنا يستخدم هذا Unicode التطبيع شكل NFKD "التوافق التحلل"


أوليفر's الجواب نقاط نص UNICODE تجزئة باعتباره السبيل الوحيد موثوق تحديد الافتراضي حدود كبيرة بين بعض عناصر النص:المستخدم ينظر الحروف والكلمات والجمل.

لهذا تحتاج خارجي مثل مكتبة rivo/uniseg, التي لا نص Unicode تجزئة.

في الحقيقة العد "رسمه المجموعة"،حيث رمز متعددة النقاط قد تكون مجتمعة في واحدة المستخدم ينظر إلى الحرف.

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

اثنين وgraphemes ، حتى وإن كانت هناك ثلاث أساطير (رمز Unicode نقطة).

نصائح أخرى

هناك طريقة للحصول على عدد الأحرف الرونية بدون أي حزم عن طريق تحويل السلسلة إلى []rune as len([]rune(YOUR_STRING)):

package main

import "fmt"

func main() {
    russian := "Спутник и погром"
    english := "Sputnik & pogrom"

    fmt.Println("count of bytes:",
        len(russian),
        len(english))

    fmt.Println("count of runes:",
        len([]rune(russian)),
        len([]rune(english)))

}

عدد البايتات 30 16

عدد الرونية 16 16

يعتمد الكثير على تعريفك لما هو "حرف".إذا كان "Rune يساوي حرف" على ما يرام لمهمتك (عموما ليس)، فإن الإجابة بواسطة Vonc مثالية لك.خلاف ذلك، يجب الإشارة إلى أن هناك حالات قليلة حيث يكون عدد الرونية في سلسلة Unicode قيمة مثيرة للاهتمام.وحتى في تلك المواقف، من الأفضل، إن أمكن، لاستنتاج العد أثناء "اجتياز" السلسلة حيث تتم معالجة الرونية لتجنب مضاعفة جهود فك شفرة UTF-8.

إذا كنت بحاجة إلى تناول مجموعات Grapeme في الاعتبار، استخدم وحدة Regoxp أو Unicode.تحسب العد عدد نقاط التعليمات البرمجية (الرصيد) أو البايتات أيضا للحصول على ValidaISON لأن طول الكتلة Grapeme غير محدود.إذا كنت ترغب في القضاء على تسلسل طويل للغاية، فحدد ما إذا كانت التسلسلات تتفق مع تنسيق النص الآمن STATW . giveacodicetagpre.

يجب أن أشير إلى أن أي من الإجابات المقدمة حتى الآن يمنحك حتى الآن عدد الأحرف كما تتوقع، خاصة عندما تتعامل مع الرموز التعبيرية (ولكن أيضا بعض اللغات مثل التايلاندية والكورية أو العربية). اقتراحات Vonc ستخرج ما يلي: giveacodicetagpre.

ذلك لأن هذه الطرق تعتمد فقط نقاط رمز Unicode فقط. هناك العديد من الأحرف التي يمكن أن تتكون من نقاط كود متعددة.

نفسه لاستخدام حزمة التطبيع : giveacodicetagpre.

التطبيع ليس حقا نفس العد أحرف ولا يمكن تطبيع العديد من الأحرف في معادل نقطة واحدة في نقطة واحدة.

p> href="https://stackoverflow.com/a/26728555/2046109"> إجابة Masakielastic تأتي قريبة ولكن فقط يعالج المعدلات (يحتوي علامات قوس قزح على معدل لا يحسب ذلك بنفسه نقطة رمز): giveacodicetagpre.

الطريقة الصحيحة لتقسيم أحرف Unicode في (الأحرف المتصورة للمستخدم)، يتم تعريف مجموعات IE Grapheme، في Unicode Standard Annex # 29 . يمكن العثور على القواعد في القسم 3.1.1 . github.com/rivo/uniseg تنفذ الحزمة هذه القواعد حتى تتمكن من تحديد العدد الصحيح من الأحرف في سلسلة: giveacodicetagpre.

هناك عدة طرق للحصول على طول السلسلة: giveacodicetagpre.

حاولت القيام به للقيام بالتطبيع أسرع قليلا: giveacodicetagpre.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top