Python ordena por valor de byte por defecto, lo que significa que é viene después de zy otras cosas igualmente divertidas. ¿Cuál es la mejor manera de ordenar alfabéticamente en Python?
¿Hay una biblioteca para esto? No pude encontrar nada. Preferiblemente, la ordenación debe tener soporte de idioma para que entienda que åäö debe ser ordenada después de z en sueco, pero que ü debe ser ordenada por u, etc. Por lo tanto, la compatibilidad con Unicode es prácticamente un requisito.
Si no hay una biblioteca para ello, ¿cuál es la mejor manera de hacerlo? ¿Simplemente haga una asignación de letra a un valor entero y asigne la cadena a una lista de enteros con eso?
locale.strcoll
respuesta es correcta cuando necesita ordenar Unicode usando la configuración regional del usuario, y la UCI responde lo que desea cuando necesita más que eso (clasificación usando más de una configuración regional). La mayoría de las veces, quiereslocale.strcoll
.locale.strcoll
funciona y especialmente qué hace ICU mejor que la función Python. Básicamente un poco más de atención a la pregunta.--locale=de__phonebook
cuando lo necesite. El módulo Perl pasa el conjunto de pruebas UCA, y el script que proporcioné hace que sea mucho más fácil jugar con todo el UCA más todas sus opciones, incluidas las configuraciones regionales, solo desde la línea de comandos. Puede que no responda a la pregunta, pero aún así debería ser muy interesante. Si estás en Suiza, estoy seguro de que podrías aprovechar la flexibilidad. :)Respuestas:
La biblioteca ICU de IBM hace eso (y mucho más). Tiene enlaces de Python: PyICU .
Actualización : la diferencia principal en la clasificación entre ICU y
locale.strcoll
es que ICU usa el algoritmo de clasificación Unicode completo mientras questrcoll
usa ISO 14651 .Las diferencias entre esos dos algoritmos se resumen brevemente aquí: http://unicode.org/faq/collation.html#13 . Estos son casos especiales bastante exóticos, que rara vez deberían importar en la práctica.
fuente
locale.strxfrm
la respuesta de u0b34a0f6ae y parece funcionar y es mucho más elegante y no requiere ningún software adicional.sudo pip3 install PyICU
no se instala y también lo hace para Python2.No veo esto en las respuestas. Mi aplicación se ordena de acuerdo con la configuración regional usando la biblioteca estándar de Python. Es bastante sencillo.
Pregunta para Lennart y otras personas que responden: ¿Nadie sabe 'locale' o no está a la altura de esta tarea?
fuente
Pruebe el algoritmo de intercalación Unicode de Python de James Tauber . Puede que no funcione exactamente como usted desea, pero parece que vale la pena echarle un vistazo. Para obtener más información sobre los problemas, consulte esta publicación de Christopher Lenz.
fuente
También te puede interesar pyuca :
http://jtauber.com/blog/2006/01/27/python_unicode_collation_algorithm/
Aunque ciertamente no es la forma más exacta, es una forma muy sencilla de al menos hacerlo bien. También supera a la configuración regional en una aplicación web, ya que la configuración regional no es segura para subprocesos y establece la configuración de idioma en todo el proceso. También es más fácil de configurar que PyICU, que se basa en una biblioteca C externa.
Subí el script a github ya que el original estaba caído en el momento de escribir este artículo y tuve que recurrir a cachés web para obtenerlo:
https://github.com/href/Python-Unicode-Collation-Algorithm
Utilicé con éxito este script para ordenar con cordura texto alemán / francés / italiano en un módulo plone.
fuente
Un resumen y una respuesta ampliada:
locale.strcoll
bajo Python 2, ylocale.strxfrm
de hecho resolverá el problema, y hace un buen trabajo, asumiendo que tiene instalada la configuración regional en cuestión. También lo probé en Windows, donde los nombres de las configuraciones regionales son confusamente diferentes, pero por otro lado parece tener todas las configuraciones regionales compatibles instaladas de forma predeterminada.ICU
no necesariamente hace esto mejor en la práctica, sin embargo, hace mucho más . En particular, tiene soporte para divisores que pueden dividir textos en diferentes idiomas en palabras. Esto es muy útil para idiomas que no tienen separadores de palabras. Necesitará tener un corpus de palabras para usar como base para la división, porque eso no está incluido.También tiene nombres largos para las configuraciones regionales, por lo que puede obtener bonitos nombres para mostrar para la configuración regional, compatibilidad con otros calendarios además del gregoriano (aunque no estoy seguro de que la interfaz de Python lo admita) y toneladas y toneladas de otras configuraciones regionales más o menos oscuras. .
Entonces, en general: si desea ordenar alfabéticamente y según la configuración regional, puede usar el
locale
módulo, a menos que tenga requisitos especiales, o también necesite más funciones dependientes de la configuración regional, como el divisor de palabras.fuente
Veo que las respuestas ya han hecho un excelente trabajo, solo quería señalar una ineficiencia de codificación en Human Sort . Para aplicar una traducción selectiva char-by-char a una cadena Unicode s, usa el código:
Python tiene una forma mucho mejor, más rápida y más concisa de realizar esta tarea auxiliar (en cadenas Unicode, el método análogo para cadenas de bytes tiene una especificación diferente y algo menos útil):
El dictado que le pasa al
translate
método tiene ordinales Unicode (no cadenas) como claves, por lo que necesitamos ese paso de reconstrucción del char a char originalspec_dict
. (Los valores en el dict que pasa para traducir [a diferencia de las claves, que deben ser ordinales] pueden ser ordinales Unicode, cadenas Unicode arbitrarias o Ninguno para eliminar el carácter correspondiente como parte de la traducción, por lo que es fácil especificar "ignorar un cierto carácter para fines de clasificación "," mapear ä a ae para fines de clasificación ", y similares).En Python 3, puede obtener el paso de "reconstrucción" de manera más simple, por ejemplo:
Consulte los documentos para conocer otras formas en que puede usar este
maketrans
método estático en Python 3.fuente
Para implementarlo, deberá leer sobre el "algoritmo de clasificación Unicode", consulte http://en.wikipedia.org/wiki/Unicode_collation_algorithm
http://www.unicode.org/unicode/reports/tr10/
una implementación de muestra está aquí
http://jtauber.com/blog/2006/01/27/python_unicode_collation_algorithm/
fuente
Últimamente he estado usando zope.ucol ( https://pypi.python.org/pypi/zope.ucol ) para esta tarea. Por ejemplo, ordenando el alemán ß:
zope.ucol también envuelve ICU, por lo que sería una alternativa a PyICU.
fuente
Una solución completa de UCA
La forma más sencilla, fácil y directa de hacerlo es hacer una llamada al módulo de la biblioteca Perl, Unicode :: Collate :: Locale , que es una subclase del módulo Unicode :: Collate estándar . Todo lo que necesita hacer es pasar al constructor un valor de configuración regional
"xv"
para Suecia.(Es posible que no necesariamente aprecie esto para el texto sueco, pero debido a que Perl usa caracteres abstractos, puede usar cualquier punto de código Unicode que desee, ¡sin importar la plataforma o compilación! Pocos idiomas ofrecen tal conveniencia. Lo menciono porque he luchado contra un perdiendo mucho la batalla con Java por este enloquecedor problema últimamente).
El problema es que no sé cómo acceder a un módulo de Perl desde Python, es decir, aparte de usar una llamada de shell o una tubería de dos lados. Con ese fin, le he proporcionado un script de trabajo completo llamado ucsort al que puede llamar para hacer exactamente lo que ha pedido con perfecta facilidad.
Este script es 100% compatible con el algoritmo de clasificación Unicode completo , ¡con todas las opciones de adaptación compatibles! Y si tiene un módulo opcional instalado o ejecuta Perl 5.13 o mejor, entonces tiene acceso completo a configuraciones regionales CLDR fáciles de usar. Vea abajo.
Demostración
Imagine un conjunto de entrada ordenado de esta manera:
Una clasificación predeterminada por punto de código produce:
lo cual es incorrecto según el libro de todos. Usando mi script, que usa el algoritmo de intercalación Unicode, obtienes este orden:
Ese es el tipo UCA predeterminado. Para obtener la configuración regional sueca, llame a ucsort de esta manera:
Aquí hay una demostración de entrada mejor. Primero, el conjunto de entrada:
Por punto de código, eso se ordena de esta manera:
Pero el uso del UCA predeterminado hace que se ordene de esta manera:
Pero en la configuración regional sueca, de esta manera:
Si prefiere ordenar en mayúsculas antes que en minúsculas, haga esto:
Clasificaciones personalizadas
Puede hacer muchas otras cosas con ucsort . Por ejemplo, aquí se explica cómo ordenar los títulos en inglés:
Necesitará Perl 5.10.1 o mejor para ejecutar el script en general. Para obtener soporte de configuración regional, debe instalar el módulo CPAN opcional
Unicode::Collate::Locale
. Alternativamente, puede instalar versiones de desarrollo de Perl, 5.13+, que incluyen ese módulo de manera estándar.Convenciones de llamadas
Este es un prototipo rápido, por lo que ucsort no está documentado en su mayoría. Pero esta es su SINOPSIS de qué conmutadores / opciones acepta en la línea de comando:
Sí, está bien: esa es realmente la lista de argumentos que uso para la llamada
Getopt::Long
, pero entiendes la idea. :)Si puede descubrir cómo llamar a los módulos de la biblioteca de Perl desde Python directamente sin llamar a un script de Perl, hágalo. Yo solo no sé cómo. Me encantaría aprender a hacerlo.
Mientras tanto, creo que este script hará lo que necesita hacer en todo su particular, ¡ y más! Ahora lo uso para toda la clasificación de texto. Que finalmente hace lo que he necesitado desde hace mucho, mucho tiempo.
El único inconveniente es que el
--locale
argumento hace que el rendimiento baje por los tubos, aunque es lo suficientemente rápido para una clasificación normal, no local, pero aún 100% compatible con UCA . Dado que carga todo en la memoria, probablemente no desee utilizar esto en documentos de gigabytes. Lo uso muchas veces al día, y seguro que es genial tener por fin una ordenación sensata de texto.fuente
Está lejos de ser una solución completa para su caso de uso, pero se puede echar un vistazo a la unaccent.py script desde effbot.org. Lo que básicamente hace es eliminar todos los acentos de un texto. Puede usar ese texto 'desinfectado' para ordenar alfabéticamente. (Para obtener una mejor descripción, consulte esta página).
fuente
Jeff Atwood escribió una buena publicación sobre el orden de clasificación natural , en la que vinculaba un guión que hace prácticamente lo que pides .
No es un guión trivial, de ninguna manera, pero funciona.
fuente