Pergunta

Arrrgh.Alguém sabe como criar uma função que é o equivalente de caractere multibyte do comando PHP count_chars ($ string, 3)?

De modo que retornará uma lista de APENAS UMA INSTÂNCIA de cada personagem único.Se fosse inglês e tivéssemos

"aaabggxxyxzxxgggghq xcccxxxzxxyx"

Ele retornaria "abgh qxyz" (observe que o espaço é contado).

(A ordem não é importante neste caso, pode ser qualquer coisa).

Se kanji japonês (não tenho certeza se todos os navegadores suportam isso):

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

E ele retornará apenas os 3 kanji usados:

漢字 私

Ele precisa funcionar em qualquer string codificada em UTF-8.

Foi útil?

Solução

Ei, Dave, você nunca verá este chegando.

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

O que, você pensou que eu usaria mb_substr novamente?

No idioma regex, ele procura qualquer caractere e, a seguir, uma ou mais ocorrências do mesmo caractere. A região correspondente é então substituída por um caractere correspondente.

O modificador u ativa UTF-8 modo em PCRE, no qual lida com sequências UTF-8 em vez de caracteres de 8 bits. Contanto que a string sendo processada já seja UTF-8 e o PCRE foi compilado com suporte a Unicode, isso deve funcionar bem para você.


Ei, adivinhe!

$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));

Isso usa o mesmo truque geral do código aleatório. Pegamos o comprimento da string e usamos mb_substr para extraí-la um caractere por vez. Em seguida, usamos esse caractere como uma chave em um array. Estamos aproveitando as vantagens dos arrays posicionais do PHP: as chaves são classificadas na ordem em que são definidas. Depois que examinamos a string e identificamos todos os caracteres, pegamos as teclas e as juntamos novamente na mesma ordem em que apareceram na string. Você também obtém uma contagem de caracteres por caractere com essa técnica.

Isso teria sido muito mais fácil se existisse algo como mb_str_split para acompanhar str_split .

(Nenhum exemplo de Kanji aqui, estou enfrentando um bug de copiar / colar.)


Aqui, experimente para ver o tamanho:

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
)
*/

Você deve chamar isso duas vezes , a segunda vez com a string da esquerda à direita e a string da direita à esquerda. A saída será diferente - array_diff apenas fornece o material do lado esquerdo que está faltando no direito, então você tem que fazer isso duas vezes para obter a história completa.

Outras dicas

Por favor, tente verificar a iconv_strlen função de biblioteca padrão do PHP.Não posso dizer sobre codificações orientais, mas funciona bem para idiomas europeus e do leste europeu.Em qualquer caso, dá alguma liberdade!

$name = "My string";
$name_array = str_split($name);
$name_array_uniqued = array_unique($name_array);
print_r($name_array_uniqued);

Muito mais fácil.Use str_split para transformar a frase em uma matriz com cada caractere como um elemento.Em seguida, use array_unique para remover duplicatas.Bem simples.Nada complicado.Eu gosto assim.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top