PHP метод для удаления повторяющихся символов из многобайтовой строки? - PullRequest
5 голосов
/ 24 марта 2011

Arrrgh. Кто-нибудь знает, как создать функцию, эквивалентную многобайтовому символу команды PHP count_chars ($ string, 3)?

Так, что он вернет список ТОЛЬКО ОДНОЙ ИНСТАНЦИИ каждого уникального персонажа. Если это был английский, и у нас было

"aaabggxxyxzxxgggghq xcccxxxzxxyx"

Будет возвращено «abgh qxyz» (обратите внимание, что пробел подсчитан).

(В данном случае порядок не важен, может быть любым).

Если японское кандзи (не уверен, что все браузеры будут поддерживать это):

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

И он вернет только 3 использованных кандзи:

漢字 私

Он должен работать с любой строкой в ​​кодировке UTF-8.

Ответы [ 3 ]

4 голосов
/ 24 марта 2011

Эй, Дейв, ты никогда не увидишь этого одного пришествия.

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?

В регулярном выражении он ищет любого персонажа, затем один или несколько экземпляров этого же персонажа. Соответствующая область затем заменяется одним соответствующим символом.

Модификатор 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 просто даст вам материал с левой стороны, который отсутствует справа, поэтому вам придется сделать это дважды, чтобы получить всю историю.

0 голосов
/ 11 августа 2013
$name = "My string";
$name_array = str_split($name);
$name_array_uniqued = array_unique($name_array);
print_r($name_array_uniqued);

Намного проще. Пользователь str_split, чтобы превратить фразу в массив с каждым символом в качестве элемента. Затем используйте array_unique для удаления дубликатов. Довольно просто Ничего сложного. Мне так нравится.

0 голосов
/ 24 марта 2011

Пожалуйста, попробуйте проверить стандартную библиотеку PHP iconv_strlen .Не могу сказать о восточных кодировках, но он отлично работает для европейских и восточноевропейских языков.В любом случае это дает некоторую свободу!

...