كيفية معرفة ما إذا كانت سلسلة معينة تحتوي على أحرف Unicode (esp.أحرف بايت مزدوجة)

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

  •  02-07-2019
  •  | 
  •  

سؤال

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

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

المحلول

تحتفظ جافا سكريبت بالنص داخليًا تحت اسم UCS-2، والذي يمكنه تشفير مجموعة فرعية واسعة جدًا من Unicode.

لكن هذا ليس وثيق الصلة بسؤالك حقًا.قد يكون أحد الحلول هو تكرار السلسلة وفحص رموز الأحرف في كل موضع:

function isDoubleByte(str) {
    for (var i = 0, n = str.length; i < n; i++) {
        if (str.charCodeAt( i ) > 255) { return true; }
    }
    return false;
}

قد لا يكون هذا بالسرعة التي تريدها.

نصائح أخرى

لقد استخدمت إجابة mikesamuel على هذا.ومع ذلك، فقد لاحظت ربما بسبب هذا النموذج أنه يجب أن يكون هناك شرطة مائلة واحدة فقط قبل u, ، على سبيل المثال. \u و لا \\u لجعل هذا العمل بشكل صحيح.

function containsNonLatinCodepoints(s) {
    return /[^\u0000-\u00ff]/.test(s);
}

تناسبني :)

لقد قمت بقياس الوظيفتين في الإجابات العليا واعتقدت أنني سأشارك النتائج.إليك رمز الاختبار الذي استخدمته:

const text1 = `The Chinese Wikipedia was established along with 12 other Wikipedias in May 2001. 中文維基百科的副標題是「海納百川,有容乃大」,這是中国的清朝政治家林则徐(1785年-1850年)於1839年為`;

const regex = /[^\u0000-\u00ff]/; // Small performance gain from pre-compiling the regex
function containsNonLatinCodepoints(s) {
    return regex.test(s);
}

function isDoubleByte(str) {
    for (var i = 0, n = str.length; i < n; i++) {
        if (str.charCodeAt( i ) > 255) { return true; }
    }
    return false;
}

function benchmark(fn, str) {
    let startTime = new Date();
    for (let i = 0; i < 10000000; i++) {
        fn(str);
    }   
    let endTime = new Date();

    return endTime.getTime() - startTime.getTime();
}

console.info('isDoubleByte => ' + benchmark(isDoubleByte, text1));
console.info('containsNonLatinCodepoints => ' + benchmark(containsNonLatinCodepoints, text1));

عند تشغيل هذا حصلت على:

isDoubleByte => 2421
containsNonLatinCodepoints => 868

لذلك بالنسبة لهذه السلسلة المحددة، يكون حل regex أسرع بحوالي 3 مرات.

ومع ذلك، لاحظ أنه بالنسبة للسلسلة التي يكون الحرف الأول فيها هو Unicode، isDoubleByte() يعود على الفور وبالتالي فهو أسرع بكثير من التعبير العادي (الذي لا يزال يحتوي على عبء التعبير العادي).

على سبيل المثال للسلسلة 中国, ، حصلت على هذه النتائج:

isDoubleByte => 51
containsNonLatinCodepoints => 288

للحصول على أفضل ما في العالمين، ربما يكون من الأفضل الجمع بين كليهما:

var regex = /[^\u0000-\u00ff]/; // Small performance gain from pre-compiling the regex
function containsDoubleByte(str) {
    if (!str.length) return false;
    if (str.charCodeAt(0) > 255) return true;
    return regex.test(str);
}

في هذه الحالة، إذا كان الحرف الأول صينيًا (وهو أمر محتمل إذا كان النص بأكمله صينيًا)، فستكون الوظيفة سريعة وستعود على الفور.إذا لم يكن الأمر كذلك، فسيتم تشغيل التعبير العادي، والذي لا يزال أسرع من التحقق من كل حرف على حدة.

في الواقع، جميع الأحرف هي Unicode، على الأقل من وجهة نظر محرك Javascript.

لسوء الحظ، فإن مجرد وجود الأحرف في نطاق Unicode معين لن يكون كافيًا لتحديد أنك بحاجة إلى مساحة أكبر.هناك عدد من الأحرف التي تشغل تقريبًا نفس مقدار المساحة التي تشغلها الأحرف الأخرى التي تحتوي على نقاط ترميز Unicode أعلى بكثير من نطاق ASCII.علامات الاقتباس المطبعية، والأحرف ذات علامات التشكيل، وبعض رموز الترقيم، ورموز العملات المختلفة تقع خارج نطاق ASCII المنخفض ويتم تخصيصها في أماكن متباينة تمامًا على مستوى Unicode الأساسي متعدد اللغات.

بشكل عام، تختار المشاريع التي عملت عليها توفير مساحة إضافية لجميع اللغات، أو تستخدم أحيانًا جافا سكريبت لتحديد ما إذا كانت النافذة التي تحتوي على سمات CSS لشريط التمرير التلقائي تحتوي بالفعل على محتوى بارتفاع قد يؤدي إلى تشغيل شريط التمرير أم لا.

إذا كان اكتشاف وجود أحرف CJK أو عددها كافيًا لتحديد أنك بحاجة إلى القليل من المساحة الإضافية، فيمكنك إنشاء تعبير عادي باستخدام النطاقات التالية:[\u3300-\u9ff\uf900-\ufaff]، واستخدم ذلك لاستخراج عدد الأحرف المطابقة.(هذا قليل جدًا من الفظاظة، ويفتقد جميع الحالات غير المتعلقة بـ BMP، وربما يستبعد بعض النطاقات الأخرى ذات الصلة، ويتضمن على الأرجح بعض الأحرف غير ذات الصلة، ولكنها نقطة بداية).

مرة أخرى، ستكون قادرًا فقط على إدارة إرشاد تقريبي بدون شيء على غرار محرك عرض النص الكامل، لأن ما تريده حقًا هو شيء مثل MeasureString الخاص بـ GDI (أو ما يعادله من أي محرك عرض نص آخر).لقد مر وقت طويل منذ أن قمت بذلك، ولكن أعتقد أن أقرب مكافئ لـ HTML/DOM هو تعيين عرض على div وطلب الارتفاع (إعادة استخدام القص واللصق، لذا أعتذر إذا كان هذا يحتوي على أخطاء):

o = document.getElementById("test");

document.defaultView.getComputedStyle(o,"").getPropertyValue("height"))

هنا اختبار مرجعي: http://jsben.ch/NKjKd

وهذا أسرع بكثير:

function containsNonLatinCodepoints(s) {
    return /[^\u0000-\u00ff]/.test(s);
}

من هذا:

function isDoubleByte(str) {
    for (var i = 0, n = str.length; i < n; i++) {
        if (str.charCodeAt( i ) > 255) { return true; }
    }
    return false;
}

لماذا لا تسمح للنافذة بتغيير حجمها بناءً على ارتفاع/عرض وقت التشغيل؟

قم بتشغيل شيء مثل هذا في النافذة المنبثقة:

window.resizeTo(document.body.clientWidth, document.body.clientHeight);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top