Foros del Web » Programando para Internet » PHP »

UTF-8 y asort()

Estas en el tema de UTF-8 y asort() en el foro de PHP en Foros del Web. Hola a todos: Mi problema es el siguiente: Tengo una matriz cuyos índices se alimentan con el ID de una tabla y cuyos valores son ...
  #1 (permalink)  
Antiguo 06/06/2011, 15:59
Avatar de auttranadhie  
Fecha de Ingreso: noviembre-2008
Ubicación: Madrid (España)
Mensajes: 156
Antigüedad: 15 años, 4 meses
Puntos: 8
Pregunta UTF-8 y asort()

Hola a todos:

Mi problema es el siguiente:

Tengo una matriz cuyos índices se alimentan con el ID de una tabla y cuyos valores son una concatenación de cada registro de dicha tabla.

Para mostrar adecuadamente los registros utilizo asort() para ordenarlos y no perder el valor de los índices.

La página está codificada en UTF-8 (y así debe seguir).

El problema surge cuando ordeno los registros con asort() y los muestro en pantalla: los caracteres con tildes (i.e., acentuados) u otros elementos (p.e., diéresis, etc.) aparecen alfabéticamente por detrás de aquellos que no están alterados.

Os dejo una muestra:

Código PHP:
$array = array("1" => "Cáscara""2" => "Cascaras");
print_r($array);
asort($array);
print_r($array); 
La impresión en pantalla me devuelve lo siguiente:

Array
(
[1] => Cáscara
[2] => Cascaras
)
Array
(
[2] => Cascaras
[1] => Cáscara
)


El primer listado es la matriz sin ordenar y el segundo ordenado. Como podéis observar la palabra "Cáscara" debiera estar en primer lugar pero, sin embargo, no es así.

He de decir que he probado con natsort() y natcasesort() aunque, en ningún caso, he obtenido el resultado esperado.

Agradezco a cualquiera que pueda aportar alguna idea al respecto.

Muchas gracias a todos y un saludo.
__________________
A. Uttranadhie
  #2 (permalink)  
Antiguo 06/06/2011, 16:16
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 11 meses
Puntos: 2135
Respuesta: UTF-8 y asort()

El problema es que en la posición del texto la á esta después de a, lo que podrías hacer para ordenar es usar por ejemplo uksort() y reemplazar los acentos por los carácteres normales (ej: á por a) y al así ordenar.

Saludos.
  #3 (permalink)  
Antiguo 07/06/2011, 13:33
Avatar de auttranadhie  
Fecha de Ingreso: noviembre-2008
Ubicación: Madrid (España)
Mensajes: 156
Antigüedad: 15 años, 4 meses
Puntos: 8
Respuesta: UTF-8 y asort()

Hola:

Lo primero, disculparme en la tardanza de la respuesta, pero hasta que no he conseguido arreglarlo no me parecía lógico aparecer por estos lares.

Por fin lo he solucionado aunque no con la opción que proponía GatorV puesto que ordenaba los índices. Ha sido un poquito más complejo pero funciona perfectamente.

GatorV, en cualquier caso te agradezco la molestia que te has tomado y la ayuda aportada.

Un saludo a todos.
__________________
A. Uttranadhie
  #4 (permalink)  
Antiguo 07/06/2011, 13:38
Avatar de iviamontes  
Fecha de Ingreso: enero-2011
Ubicación: $cubano->Arg->Mendoza
Mensajes: 1.184
Antigüedad: 13 años, 3 meses
Puntos: 209
Respuesta: UTF-8 y asort()

deberias poner tu solución para la comunidad
  #5 (permalink)  
Antiguo 07/06/2011, 15:08
Avatar de auttranadhie  
Fecha de Ingreso: noviembre-2008
Ubicación: Madrid (España)
Mensajes: 156
Antigüedad: 15 años, 4 meses
Puntos: 8
Respuesta: UTF-8 y asort()

Hola, de nuevo:

Efectivamente, iviamontes, quizás lo más adecuado es poner la solución para todos.

El planteamiento es el siguiente:

Se trata de una base de datos que contiene nombres y apellidos de autores literarios. Puesto que utilizo UTF-8 dichos valores (en formato apellido, nombre) no se ordenaban bien alfabéticamente ya que los caracteres con tildes (acentuados gráficamente) u otros elementos aparecen siempre ordenados por detrás de los que no lo tienen.

Estos valores se guardan en una base de datos y se recuperan mediante consulta en una matriz cuyo índice es el ID de cada registro y el valor la concatenación de apellidos y nombre, junto con otros datos de interés (fechas, clarificadores, etc.)

La solución que encontré fue hacer uso del índice cada valor de matriz para no perder la referencia de cada valor y hacer que el mismo fuera reemplazado por uno igual pero sin caracteres acentuados, ordenar los registros adecuadamente y volver a rellenar cada valor de la matriz gracias al índice de la misma.

El código resultante ha sido el siguiente:

1.º Declaración de variables que contengan los caracteres a buscar:

Código PHP:
$pattern_a '(á|à|â|ä|Á|À|Â|Ä)';
$pattern_e '(é|è|ê|ë|É|È|Ê|Ë)';
$pattern_i '(í|ì|î|ï|Í|Ì|Î|Ï)';
$pattern_o '(ó|ò|ô|ö|Ó|Ò|Ô|Ö)';
$pattern_u '(ú|ù|û|ü|Ú|Ù|Û|Ü)'
2.º Tras la consulta y varios procesos se rellena una primera matriz dentro del while() de un recordset:

Código PHP:
$array_authority_unordered[$row_authority["authority_id"]] = $authority_name_main.$authority_name_sec.$authority_name_add.$authority_dtm
3.º Por último, con la matriz obtenida, se crea una de tipo sesión (la voy a usar a lo largo de la misma) a partir de la primera y se reemplazan los valores no deseados por aquellos que me permitan una ordenación adecuada. Cuando termina, se ordena toda la matriz y se conmutan dentro de esa matriz ordenada los valores originales para que mantengan los caracteres acentuados:

Código PHP:
if (isset($array_authority_unordered)) // Por si la matriz no existiera
{
    
$_SESSION["authority"] = $array_authority_unordered;
    foreach (
$_SESSION["authority"] as $index => $value)
    {
        
$value preg_replace($pattern_a,"a"$value);
        
$value preg_replace($pattern_e,"e"$value);
        
$value preg_replace($pattern_i,"i"$value);
        
$value preg_replace($pattern_o,"o"$value);
        
$value preg_replace($pattern_u,"u"$value);
        
$_SESSION["authority"][$index] = $value;
    }
    
asort($_SESSION["authority"]); // Ordenación de la matriz por sus valores
    
foreach ($_SESSION["authority"] as $index => $value)
    {
        foreach (
$array_authority_unordered as $index_unordered => $value_unordered)
        {
            if (
$index_unordered == $index)
            {
                
$_SESSION["authority"][$index] = $value_unordered// Conmutación del valor original por el que se ha utilizado para la ordenación
            
}
        }
    }
    unset(
$array_authority_unordered);

No es que sea gran cosa, pero funciona. Ahora bien, si alguien puede aportar algo más simple e igualmente eficaz se agradecería muchísimo.

Espero que haya sido de ayuda para todos y un saludo.
__________________
A. Uttranadhie
  #6 (permalink)  
Antiguo 07/06/2011, 15:49
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 11 meses
Puntos: 2135
Respuesta: UTF-8 y asort()

Sí de hecho podrías hacer algo así:
Código PHP:
Ver original
  1. $array = ;
  2. uksort($array, function($name1, $name2) {
  3.     $patterns = array(
  4.         'a' => '(á|à|â|ä|Á|À|Â|Ä)',
  5.         'e' => '(é|è|ê|ë|É|È|Ê|Ë)',
  6.         'i' => '(í|ì|î|ï|Í|Ì|Î|Ï)',
  7.         'o' => '(ó|ò|ô|ö|Ó|Ò|Ô|Ö)',
  8.         'u' => '(ú|ù|û|ü|Ú|Ù|Û|Ü)'
  9.     );
  10.    
  11.     $name1 = preg_replace(array_values($patterns), array_keys($patterns), $name1);
  12.     $name2 = preg_replace(array_values($patterns), array_keys($patterns), $name2);
  13.    
  14.     return strcasecmp($name1, $name2);
  15. });
  16.  
  17. var_dump($array);

Con uksort() haces un sort pero mantienes las llaves (indices).

Saludos.

* Nota el ejemplo solo es para PHP5.3, para <PHP5.2 tienes que usar un callback.
  #7 (permalink)  
Antiguo 07/06/2011, 16:27
Avatar de iviamontes  
Fecha de Ingreso: enero-2011
Ubicación: $cubano->Arg->Mendoza
Mensajes: 1.184
Antigüedad: 13 años, 3 meses
Puntos: 209
Respuesta: UTF-8 y asort()

perfecto !!!!

Etiquetas: asort, utf-8
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 07:23.