[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