ما هي الطريقة الأكثر كفاءة لحساب كل الكلمات في Richtextbox؟

StackOverflow https://stackoverflow.com/questions/2226161

سؤال

أنا أكتب محرر نصوص وتحتاج إلى توفير عدد الكلمات الحية. الآن أنا أستخدم طريقة الملحق هذه:

 public static int WordCount(this string s)
    {
        s = s.TrimEnd();
        if (String.IsNullOrEmpty(s)) return 0;
        int count = 0;
        bool lastWasWordChar = false;
        foreach (char c in s)
        {
            if (Char.IsLetterOrDigit(c) || c == '_' || c == '\'' || c == '-')
            {
                lastWasWordChar = true;
                continue;
            }
            if (lastWasWordChar)
            {
                lastWasWordChar = false;
                count++;
            }
        }
        if (!lastWasWordChar) count--;
        return count + 1;
    }

لدي تعيين بحيث يعمل عدد الكلمات على نص RichTextBox كل عشر ثانية (إذا كان بدء تشغيل الاختيار يختلف عن ما كانت عليه آخر مرة ركض الطريقة). المشكلة هي أن عدد الكلمات يحصل ببطء عند العمل على ملفات طويلة جدا. لحل هذا أنا أفكر في الحصول على عدد الكلمات التي تعمل فقط على الفقرة الحالية، تسجيل كلمة العد في كل مرة ومقارنتها ضد ما كان عدد الكلمات آخر مرة تم تشغيل عدد الكلمات. ثم ستضيف الفرق بين الاثنين إلى إجمالي عدد الكلمات. القيام بذلك سيؤدي إلى العديد من المضاعفات (إذا كان المستخدم المعاجون، إذا قام المستخدم بحذف فقرة، إلخ.) هل هذه طريقة منطقية للذهاب إلى تحسين عدد الكلمات؟ أم أن هناك شيء لا أعرفه مما يجعله أفضل؟

تحرير: هل سيعمل على تشغيل عدد الكلمات على مؤشر ترابط مختلف؟ أنا لا أعرف الكثير عن الخيوط، وسوف أبحث.

نموذج النص الذي استخدمته:

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

المحلول

يمكنك القيام بعدد كلمات أبسط بناء على المساحة البيضاء:

public static int WordCount(this string s)
{
  return s.Split(new char[] {' '}, 
    StringSplitOptions.RemoveEmptyEntries).Length;
}

يوفر MSDN هذا المثال, ، يجب أن تعطيك كلمة دقيقة عد أسرع بكثير على الملفات الكبيرة.

نصائح أخرى

يمكنك أيضا استخدام Regex بسيطة للغاية تبحث عن حرف واحد على الأقل و / أو علامة اقتباس أحادية لالتقاط الانقباضات:

public static int WordCount(this string s) 
{
    return Regex.Matches(s, @"[\w']+").Count;
}

سيؤدي ذلك إلى إرجاع 2141 مباراة (التي هي في الواقع أكثر صحة من Word في هذه الحالة لأن كلمة تحسب النجمة الفردية ككلمة في الجملة "عن طريق طعن إصبعها").

سوفيتك هي في الواقع أسرع من المقترح String.Split الطريقة، أسرع ثلاث مرات تقريبا على X86 وأكثر من مرتين بشكل أسرع في X64 في الواقع. أظن أن JIT تعبث مع توقيتك، قم دائما بتشغيل microbenchmarks الخاص بك مرتين كما سيحتل جيت الغالبية العظمى من الوقت أثناء تشغيلك الأول. ولأن String.Split لقد كان ngen'd، لا يحتاج إلى تجميعها إلى الرمز الأصلي وبالتالي يبدو أن أسرع.

ناهيك عنها أيضا أكثر دقة، String.Split سوف نحسب 7 كلمات هنا:

اختبار :: هذا اختبار

من المنطقي أيضا، String.Split لا يؤدي أي سحر، وسوف أكون مفاجئا للغاية إذا كان إنشاء مجموعة من الأوتار كثيرة سيكون أسرع من مجرد التكرار عبر الشخصيات الفردية في السلسلة. يبدو أن الإفراط في الحصول على سلسلة محسنة للغاية كما حاولت unsafe مؤشر حسابي وكان في الواقع أبطأ قليلا قليلا من بسيطة foreach. وبعد أشك حقا أن هناك بأي طريقة للقيام بذلك بشكل أسرع، بخلاف أن تكون ذكية حول الأقسام في النص الخاص بك تحتاج إلى عدد الكلمات.

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