Aujourd’hui, une personne demandait sur la mailling list Rails comment trier des chaînes de caractères contenant des accents.
En effet…
["az","aea","aéb"].sort
# => ["aea", "az", "aéb"]
La solution (la plus simple ?) consiste à remplacer les lettres accentuées par leur équivalent sans accent et à faire le tri sur les chaînes ainsi transformées. Pour cela nous utiliserons le fait que la méthode String.sort peut prendre en paramètre un bloc permettant de préciser la méthode de comparaison entre deux éléments. Donc; imaginons que nous ayons une méthode String.no_accent, nous pouvons donc faire cela :
["az","aea","aéb"].sort { |x, y| x.no_accent <=> y.no_accent }
Malheureusement, la méthode String.no_accent n’existe pas… Et bien, créons là :
class String
def no_accent
self.
tr_s( ‘ÁÀÂÄÃÅÇÉÈÊËÍÏÎÌÑÓÒÔÖÕÚÙÛÜÝáàâäãåçéèêëíìîïñóòôöõúùûüýÿ’,
‘AAAAAACEEEEEIIIINOOOOOUUUUYaaaaaaceeeeiiiinooooouuuuyy’ )
end
end
puts ["az","aea","aéb"].sort { |x, y| x.no_accent <=> y.no_accent }
# => ["aea", "aéb", "az"]
Une autre solution consiste à passer par les entités html :
class String
def no_accent
require ‘rubygems’
require ‘htmlentities’
HTMLEntities.
new.
encode( self,
:named ).
gsub( /\&
([A-za-z
])(?:acute|cedil|circ|grave|ring|tilde|uml
)\;/,
‘\1‘ ).
gsub( /\&
([A-za-z
]{2})(?:lig
)\;/,
‘\1‘ ).
gsub( /\&
[^;
]+\;/,
” )
end
end
["az","aea","aéb"].sort { |x, y| x.no_accent <=> y.no_accent }
# => ["aea", "aéb", "az"]
Et enfin il y a la solution qui utilise unicode :
$KCODE = ‘u’
class String
def no_accent
require ‘rubygems’
require ‘unicode’
Unicode.normalize_KD(self).unpack(‘U*’).select{ |cp|
cp < 0×0300 || cp > 0×036F
}.pack(‘U*’)
end
end
["az","aea","aéb"].sort { |x, y| x.no_accent <=> y.no_accent }
# => ["aea", "aéb", "az"]