[Python-es] Ordenando con strcoll

Oswaldo Hernández listas en soft-com.es
Mar Feb 9 11:16:37 CET 2010


Oswaldo Hernández escribió:
> Sio2 escribió:
>> Estoy intentando ordenar una serie de nombres alfabéticamente, pero hago
>> algo mal o esta función no me va.
>>
>> Veamos:
>> $ python
>> Python 2.5.4 (r254:67916, Nov 19 2009, 22:14:20)
>> [GCC 4.3.4] on linux2
>> Type "help", "copyright", "credits" or "license" for more information.
>>>>> import locale
>>>>> locale.setlocale(locale.LC_ALL,'')
>> 'es_ES en euro'
>>>>> a="Diaz Flor, M"
>>>>> b="Diaz Flores, M"
>>
>>
>> Como veis no pongo ni los acentos para poder usar cmp:
>>
>>>>> cmp(a,b)
>> -1
>>
>> Lo esperable, "a" va antes que "b". Sin embargo:
>>
>>>>> locale.strcoll(a,b)
>> 8
>>
>> "b" antes que "a" y, como consecuencia, el listado no sale ordenado
>> correctamente.
>>
>> ¿Se me escapa algo? ¿No funciona bien strcoll?
>>
>> (Con es_ES.UTF-8 me sucede exactamente lo mismo)
>>
> 
> El ordenamiento con las funciones de locale es muy distinto al 
> ordenamiento ascii habitual. Cada texto se evalúa en función de reglas 
> de peso en donde los espacios, y otros caracteres apenas pesan.
> 
> Esto hace que a veces lo veamos de forma extraña, pero tiene su lógica y 
> sus ventajas.
> 
> Ejemplos:
> 
>  >>> locale.strcoll("'''Miguel'''", "Alberto")
> 12
> 
>  >>> locale.strcoll("      Juan", "Adrian")
> 9
> 
> En el caso que muestras strcoll practicamente lo que está haciendo es 
> comparar "DiazFlorM" con "DiazFloresM", omitiendo (o casi) los espacios 
> y las comas ya que su peso es ínfimo.
> 
> En una base de datos que utilice el locale para ordenar veras que el 
> comportamiento es similar.
> 
> (PostgreSQL 8.3)
> 
> select 'Diaz, M'
> union
> select 'Diaz Flor, M'
> union
> select 'Diaz Flores, M'
> order by 1 asc;
> 
> 
>     ?column?
> ----------------
>  Diaz Flor, M
>  Diaz Flores, M
>  Diaz, M
> (3 filas)
> 

En este ejemplo la ordenación no es la que pretendía, pero sirve para 
ilustrar el como funciona LC_COLLATE ;)

La consulta esta hecha el una base de datos instalada en windows con 
lc_collate establecido a:

postgres=# show lc_collate;
      lc_collate
--------------------
  Spanish_Spain.1252
(1 fila)

Si embargo si repito lo mismo en otra base de datos instalada en linux 
con LC_COLLATE:

postgres=# show lc_collate;
  lc_collate
-------------
  es_ES.UTF-8
(1 fila)

postgres=# select 'Diaz, M' union select 'Diaz Flor, M' union select 
'Diaz Flores, M' order by 1 asc;
     ?column?
----------------
  Diaz Flores, M
  Diaz Flor, M
  Diaz, M
(3 filas)


Saludos,


-- 
*****************************************
Oswaldo Hernández
oswaldo (@) soft-com (.) es
*****************************************
PD:
Antes de imprimir este mensaje, asegúrese de que es necesario.
El medio ambiente está en nuestra mano.



Más información sobre la lista de distribución Python-es