jeudi, février 21, 2008

Enlever les lignes en double dans un fichier

Une petie astuce que j'ai posté sur le blog de torsten en réponse à sa question:
Comment afficher les lignes d'un fichier en enlevant les doublons (faire une sorte de 'unique' ou 'distinct' sur les lignes du fichier)

Je me suis dit que ça pourrait servir à d'autres donc je le repost ici:
puts IO.readlines('data.txt').uniq

Par contre sur un gros fichier ça doit consommer beaucoup de mémoire...

Technorati tags:

mardi, février 19, 2008

Convertir de l'utf-16 en iso-8859-1

Je savais que la gestion de l'utf en ruby (1.8) était un gros problème auquel je n'avais pas encore été confronté. Mais dans mon cas le plus gros problème a été de trouver une page web qui m'explique comment faire au lieu de se plaindre :(

Il y a tellement de pages sur des forums etc... qui expliquent qu'il y a un problème sans fournir de solution claire!

Finallement je suis tombé sur cette page de Obie qui m'a mis sur la bonne piste :)

Malheureusement dans son exemple je perdais les accents (c'est embêtant :( )

Voilà l'exemple corrigé pour transfromer de l'UTF-16 vers de l'ISO-8859-1. Pour UTF-8 il suffit de remplacer 16 par 8 étonnant non ? ;)



require 'iconv'

class String
  def utf16_to_iso
    converter = Iconv.new('ISO-8859-1//IGNORE//TRANSLIT', 'UTF-16')
    converter.iconv(self)
  end
end

content = IO.read("utf16.txt").utf16_to_iso
content.split("\n").each do |line|
  do_something(line)
end

IGNORE veut dire que Iconv va ignorer les erreurs de conversion. Si vous voulez être prévenu quand vous avez un caractère exotique, enlevez cette option.


TRANSLIT essaye de trouver le caractère le plus proche de celui de utf dans iso.

Petite astuce UTF-16, je n'ai pas pu utiliser la méthode: IO.foreach que j'aime beaucoup en temps normal parce que cette méthode split sur le caractère "\n" or en UTF-16 comme c'est stocké sur deux octets le retour à la ligne est "\n\000". J'ai donc converti la chaine avant de faire le split.


Technorati tags:

vendredi, février 15, 2008

Comment tester null ou chaine (string) vide

Récemment dans un petit script j'avais le code suivant:
unless(item.nil? or item.emty?)
  ...
end
Où item est soit nil, soit "", soit "foo". Je n'aimais pas faire ça partout dans le code, je voulais être plus "DRY" en faisant quelque chose comme:
unless(item.blank?)
  ...
end
La solution que j'ai trouvé dans un premier temps pour résoudre ce problème "esthétique" était de déclarer la fonction blank? dans String et NilClass; ça conne ça:

class NilClass
  def blank?
    true
  end
end

class String
  def blank?
    to_s.empty?
  end
end
Mais Benjamin C. m'a montrer une manière plus élégante en étendant Object:
class Object
  def blank?
    respond_to?(:empty?) ? empty? : !self
  end
end
Code re-pompé honteusement de rails.
Technorati tags: