Quiero obtener la palabra más utilizada de una matriz. El único problema es que los caracteres suecos (Å, Ä y Ö) solo se mostrarán como �.

$string = 'This is just a test post with the Swedish characters Å, Ä, and Ö. Also as lower cased characters: å, ä, and ö.';
echo '<pre>';
print_r(array_count_values(str_word_count($string, 1, 'àáãâçêéíîóõôúÀÁÃÂÇÊÉÍÎÓÕÔÚ')));
echo '</pre>';

Ese código generará lo siguiente:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [�] => 1
    [�] => 1
    [and] => 2
    [�] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [�] => 1
    [�] => 1
    [�] => 1
)

¿Cómo puedo "ver" los caracteres suecos y otros caracteres especiales?

3
Airikr 24 sep. 2016 a las 14:36

3 respuestas

La mejor respuesta

Aquí hay una solución con expresiones regulares que usan puntuación Unicode para dividir las "palabras" y luego solo un recuento de ocurrencias de matriz regular.

array_count_values(preg_split('/[[:punct:]\s]+/u', $string, -1, PREG_SPLIT_NO_EMPTY));

Produce:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [Å] => 1
    [Ä] => 1
    [and] => 2
    [Ö] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [å] => 1
    [ä] => 1
    [ö] => 1
)

Esto se probó en una consola Unicode, es posible que desee imponer una codificación si está utilizando un navegador. Cree una etiqueta <meta> o configure la codificación dentro de su navegador, o envíe encabezados PHP.

1
Mr Lister 3 oct. 2016 a las 17:04

Me las arreglé para quitar el signo � agregando ÅåÄäÖö en àáãâçêéíîóõôúÀÁÃÂÇÊÉÍÎÓÕÔÚ.

0
Airikr 24 sep. 2016 a las 13:15

Todo esto se ejecuta asumiendo que estás usando UTF-8.

Puede adoptar un enfoque ingenuo utilizando preg_split() para dividir su cadena en cualquier separador, puntuación o carácter de control.

Ejemplo de preg_split:

$split = preg_split('/[\pZ\pP\pC]/u', $string, -1, PREG_SPLIT_NO_EMPTY);
print_r(array_count_values($split));

Salida:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [Å] => 1
    [Ä] => 1
    [and] => 2
    [Ö] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [å] => 1
    [ä] => 1
    [ö] => 1
)

Esto funciona bien para su cadena dada, pero no necesariamente divide las palabras de una manera que tenga en cuenta la configuración regional. Por ejemplo, contracciones como "no" se dividirían en "isn" y "t" por esto.


Afortunadamente, la extensión Intl agrega una gran cantidad de funciones para lidiar con cosas como esta en PHP 7.

El plan sería:

(* Tenga en cuenta que probablemente desee realizar la normalización independientemente del método que utilice para dividir la cadena; sería apropiado hacerlo antes del preg_split anterior o lo que decida utilizar. )

Ejemplo internacional:

$string = Normalizer::normalize($string);

$iter = IntlBreakIterator::createWordInstance("sv_SE");
$iter->setText($string);
$words = $iter->getPartsIterator();

$split = [];
foreach ($words as $word) {
    // skip text fragments consisting only of a space or punctuation character
    if (IntlChar::isspace($word) || IntlChar::ispunct($word)) {
        continue;
    }
    $split[] = $word;
}

print_r(array_count_values($split));

Salida:

Array
(
    [This] => 1
    [is] => 1
    [just] => 1
    [a] => 1
    [test] => 1
    [post] => 1
    [with] => 1
    [the] => 1
    [Swedish] => 1
    [characters] => 2
    [Å] => 1
    [Ä] => 1
    [and] => 2
    [Ö] => 1
    [Also] => 1
    [as] => 1
    [lower] => 1
    [cased] => 1
    [å] => 1
    [ä] => 1
    [ö] => 1
)

Esto es más detallado pero puede valer la pena si prefiere ICU (la biblioteca que respalda la extensión Intl) para hacer el trabajo pesado cuando se trata de comprender lo que constituye una palabra.

4
user3942918 24 sep. 2016 a las 14:51