طريقة PHP لتجريد الأحرف المكررة من سلسلة متعددة البايت؟

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

  •  29-10-2019
  •  | 
  •  

سؤال

أررغ.هل يعرف أحد كيفية إنشاء وظيفة تمثل الأحرف متعددة البايت المكافئة لأمر PHP count_chars($string, 3)؟

بحيث تقوم بإرجاع قائمة بمثيل واحد فقط لكل حرف فريد.إذا كانت تلك هي اللغة الإنجليزية وكان لدينا

"aaabggxxyxzxxggggghq xcccxxxzxxyx"

سيُرجع "abgh qxyz" (لاحظ أنه تم حساب المسافة).

(الترتيب ليس مهما في هذه الحالة، يمكن أن يكون أي شيء).

إذا كان كانجي الياباني (لست متأكدًا من أن جميع المتصفحات ستدعم هذا):

漢漢漢字漢字私私字私字漢字私漢字漢字私

وسيقوم بإرجاع الكانجي الثلاثة المستخدمة فقط:

شكرا جزيلا

يجب أن يعمل على أي سلسلة مشفرة UTF-8.

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

المحلول

مرحبًا ديف، لن ترى أبدًا هذا واحد قادم.

php > $kanji = '漢漢漢字漢字私私字私字漢字私漢字漢字私';
php > $not_kanji = 'aaabcccbbc';
php > $pattern = '/(.)\1+/u';
php > echo preg_replace($pattern, '$1', $kanji);
漢字漢字私字私字漢字私漢字漢字私
php > echo preg_replace($pattern, '$1', $not_kanji);
abcbc

ماذا، كنت أعتقد أنني سوف تستخدم mb_substr مرة أخرى؟

في regex-speak، يبحث عن أي حرف واحد، ثم مثيل واحد أو أكثر من نفس الحرف.يتم بعد ذلك استبدال المنطقة المطابقة بالحرف الواحد المطابق.

ال u المعدل يقوم بتشغيل وضع UTF-8 في PCRE الذي يتعامل معه تسلسل UTF-8 بدلاً من أحرف 8 بت.طالما أن السلسلة التي تتم معالجتها هي UTF-8 بالفعل و تم تجميع PCRE بدعم Unicode، ومن المفترض أن يعمل هذا بشكل جيد بالنسبة لك.


مهلا، خمن ماذا!

$not_kanji = 'aaabbbbcdddbbbbccgggcdddeeedddaaaffff';
$l = mb_strlen($not_kanji);
$unique = array();
for($i = 0; $i < $l; $i++) {
    $char = mb_substr($not_kanji, $i, 1);
    if(!array_key_exists($char, $unique))
        $unique[$char] = 0;
    $unique[$char]++;
}
echo join('', array_keys($unique));

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

كان من الممكن أن يكون هذا أسهل بكثير لو كان هناك شيء مثل mb_str_split للذهاب جنبا إلى جنب مع str_split.

(لا يوجد مثال كانجي هنا، فأنا أواجه خطأ في النسخ/اللصق.)


هنا، جرب هذا بالنسبة للحجم:

function mb_count_chars_kinda($input) {
    $l = mb_strlen($input);
    $unique = array();
    for($i = 0; $i < $l; $i++) {
        $char = mb_substr($input, $i, 1);
        if(!array_key_exists($char, $unique))
            $unique[$char] = 0;
        $unique[$char]++;
    }
    return $unique;
}

function mb_string_chars_diff($one, $two) {
    $left = array_keys(mb_count_chars_kinda($one));
    $right = array_keys(mb_count_chars_kinda($two));
    return array_diff($left, $right);
}

print_r(mb_string_chars_diff('aabbccddeeffgg', 'abcde'));
/* => 
Array
(
    [5] => f
    [6] => g
)
*/

سترغب في الاتصال بهذا مرتين, ، والمرة الثانية بالوتر الأيسر على اليمين، والوتر الأيمن على اليسار.سيكون الناتج مختلفًا - array_diff يمنحك فقط الأشياء الموجودة في الجانب الأيسر والمفقودة من الجانب الأيمن، لذا عليك القيام بذلك مرتين للحصول على القصة بأكملها.

نصائح أخرى

الرجاء محاولة التحقق من iconv_strlen وظيفة مكتبة PHP القياسية.لا يمكن الحديث عن ترميزات المشرق ، لكنها تعمل بشكل جيد مع اللغات الأوروبية وأوروبا الشرقية.على أي حال فإنه يعطي بعض الحرية!

Genacodicetagpre

أسهل بكثير.المستخدم str_split لتحويل العبارة إلى مصفوفة مع كل حرف كعنصر.ثم استخدم array_unique لإزالة التكرارات.بسيط جدا.لا شيء معقد.أنا أحب ذلك بهذه الطريقة.

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