mardi 3 janvier 2012
Regexp en PERL
s'utilise avec les commandes suivantes:
m (match)
s (substitute) :/i (case insensitive)/g global
tr ou y (translation) /ex s/ba/ab/g ne marche pas par contre y/ba/ab/ lui fonctionne bien.
charactère spéciaux:
\s : space
\S : non space
\d : digit
\D : non digit
\w : word
Exemple : récupérer et supprimer le dernier espace dans une chaine de caracètre:
$str=~s/(\s+\S*$)//;
print $1;
Je recherche au moins un espacedans une chaine qui se termine par 0 ou 1 non espace.
Perl stocke le contenu de la paranthèse (\s+\S*$) dans la variable $1
Trim d'une chaine de caractère
$str=~s/^\s+//; # éliminie les espaces de débuts
$str=~s/\s+$//; # élimine les espaces de fins
Vérification d'une adresse mail (simple):
$str~=m/[a-zA-Z0-9-.]+\@[a-zA-Z0-9-.]+
Vérifier qu'une chaine de caractère contient un opérateur:
$str~=m/\*|\+|\/|\\|\(|\)|\s|\^|#|\||'|\"|=|!
vendredi 21 octobre 2011
Tableaux de hashmap
my %h1 = ("toto"=>"toto12", "test"=>"test12");
my %h2 = ("xavier"=>"0471...", "vincent"=>"047945...");
Il n'est pas permis d'écrire ceci en Perl
my @array=undef;
@array[0]=%h1;
@array[1]=%h2;
Il est impératif de référencer les hashmap dans le tableau:
my @array=undef;
@array[0]=\%h1;
@array[1]=\%h2;
Ceci fonctionnera beaucoup mieux.
Là où cela devient amusant c'est pour récupérer les hashmap contenue dans le tableau:
$array[1]->{vincent} me donnera 047945...
si je veux defnir %hmap qui contiendra la hash contenue dans $array[1] je pourrais faire comme suit:
%hmap=%$array[1];
Cela fera malheureusement planter PERL lamentablement.
soit j'écris
$hmap_ref=$array[1];
%hmap=%$hmap_ref;
Cela marchera mais pour un développeur PERL cette écriture est beaucoup trop lourde:
On pourra donc faire plus concis (et plus illisible) en utilisant ceci:
%hmap=%{$array[1]}
Attention c'est la déréférenciation d'un tableau et non pas la valeur de la clé d'une hash (dont la clé serait $array[1]).
Voilà de quoi s'amuser. ..
lundi 17 octobre 2011
Hashmap en Perl
Tout d’abord une hash est une structure de données référencée par une clé généralement alphanumérique :
(Nom=clé) => Numéro de téléphone
Exemple :
Vincent => +3271546521
La clé sera ici vincent et la valeur associée, +32 blabla. En général on applique un hashage sur la clé (ou un digest) pour transformer la séquence de caractère en un integer plus ou moins unique par chaîne de caractère. Ceci a tendance à améliorer la rapidité des traitements.
Création d’une hash (hashmap)
my %h=( "jyce"=>"071456502",
"toto"=>"toto12");
La hash est un type particulier en PERL représenté par ‘%’
Toute variable déclarée avec un % est une hashmap
Pour obtenir le numéro de tel de jyce :
print $h{jyce} ; # attention pas %{}
Une fois crée il est toujours possible d’ajouter des nouveaux couples clé-valeur dans la hashmap.
# oups oublié, on rajoute directement comme des cochons dans la hashmap
$h{"marc"}="071726532";
Fusionner deux hashmap :
my %h2 = ("vincent"=>"04754455",
"xavier"=>"0479581515");
%h=(%h,%h2); # pas mal hein ?
Afficher l’entiereté d’une hashmap
print "$_=".$h{$_}."\n" foreach (keys(%h)) ;
keys(%h) est une fonction qui renvoit un tableau contenant les clés de la hash :
@k=keys(%h) ;
Par métaphore, $_ représente donc un élément du tableau @k.
Nous allons créer une procédure qui affiche la hashmap :
sub map_params {
my (%m)=@_;
print "Non triée\n";
print "$_=".$m{$_}."\n" foreach (keys(%m)) ;
}
#appel
map_params(%h)
Référencer une hashmap. Dans certains cas de figure il est impératif d’utiliser une référence sur la hashmap.
Créeonns une procédure attendant une hashmap en paramètres, cette procédure aura ainsi par exemple la faculté d’ajouter des choses dans la hashmap et de faire en sorte que ces choses soient toujours là après l’appel (passage par référence) :
sub map_params_ref {
my ($mref)=shift;
map_params(%$mref); # déférenciation et on appel la proc standard d’affichage
}
#appel
map_params_ref(\%h);
remarquez que $mref->{vincent} fonctionne aussi très bien, je n’ai pas besoin dans ce cas de déréférencer.
Afficher une hashmap triée :
Je trie le tableau des clés et j’affiche les valeurs en parcourant le tableau de clé trié :
print "Triée\n";
my @key_sorted=sort ( {$a cmp $b} keys(%m) );
print $_.'='.$m{$_}."\n" foreach (@key_sorted);
trier dans l’ordre descendant
my @key_sorted=sort ( {$b cmp $a} keys(%m) );
Voilà j’espère que ce petit tuto sur les manipulations de hash vous a amusé...
vendredi 14 octobre 2011
Sub en PERL
Voyons quelques exemples:
Passer des paramètres à une sub
Définissons une fonction qui somme deux paramètres a et b : façon propre de faire
sub sum {
my ($a,$b)=@_;
return $a+$b;
}
Bon l’explication est simple, les paramètres d’une sub sont un tableau référencé par @_
La notation ($var1, $var2, … , $varn) permet de récupérer les éléments d’un tableau dans l’ordre 1 ..n
Mais pourquoi faire simple quand on peut faire compliquer , PERL va offrir d’atures méchanismes d’extraction dans un tableau
Ex :façon longue
sub sum {
my $a=shift(@_);
my $b=shift(@_);
return $a+$b;
}
Shift permet de retirer des éléments d’un tableau, (le premier entré est le premier sortant FIFO)
Façon plus simple
sub sum {
my $a=shift;
my $b=shift;
return $a+$b;
}
Dans une sub le paramètre @_ est implicite shift s’appliquera donc d’office à lui si rien n’est précisé.
Façon LIFO
sub sum {
my $b=pop;
my $a=pop;
return $a+$b;
}
Attention dans une LIFO le dernier entré est le premier à sortir (pile d'assiettes)
Façon bête :
sub sum{
my $a=$_[0];
my $b=$_[1];
return $a+$b;
}
Remarqué qu’ici on utilise $_[i] puisqu’on référence un élément du tableau qui est scalaire.
Ici nous avons vu le passage par valeur, il n’est pas possible de modifier les paramètres, voyons maintenant le passage par adresse.
Si je passe des variables en paramètre à cette fonction, la valeur des paramètres est copiée dans la fonction.
Donc toute modification apportée aux variables ne sera pas répercutée en dehors de la fonction.
Considérons la fonction suivante :
sub sum_ref {
my ($aref,$bref)=@_;
$$aref=3; # je remplace le paramètre entré 5 par 3.
my $a=$$aref; # je déférence dans $a
my $b=$$bref; # je déférence dans $b
return $a+$b;
}
my $x=5;
my $y=6;
print sum_ref(\$x,\$y);
print "\n$x";
Vous l’aurez compris la sortie va me donner ceci :
9
3
$x vallait cinq mais c’est son adresse qui a été passée. Donc c’est la valeurs contenue à cette adresse logique qui a été remplacée par 3.
Remarquez le bel opérateur de référencement \$var et l’opérateur de déréférencement $$var qui donne au coding une élégance digne des soirées de Monsieur l’Ambassadeur.
En conclusion je rapellerai cette magnifique citation de Dave Small :
Un langage de programmation est censé être une façon conventionnelle de donner des ordres à un ordinateur. Il n'est pas censé être obscur, bizarre et plein de pièges subtils ça, ce sont des attributs de la magie.
Il devait certainement penser à PERL lorsqu’il a écrit cela.
vendredi 30 septembre 2011
La classe box-plot
Ce petit framework permet de créer un objet de type Raphael, cet objet fournit un canvas sur un panel div contenu dans le browser.
L'utilité d'un framework n'est plus à démontrer puisqu'il permet:
- de ne pas ré-inventer la roue
- de déléguer à d'autres personnes plus expertes des tâches secondaires pour notre projet
- de se focaliser sur notre propre business
- de profiter des évolutions et des améliorations du framework sans devoir mettre les mains dans le camboui.
Ce canvas supporte différente méthode graphiques donc la méthode « path » basée sur une notation SVG (Scale Vector Graphics).
Path prend comme une paramètre une string constituée des attributs suivant : M x y, ce qui signifie MoveTo (x,y) en pixel et L x y, ce qui signifie LineTo.
Une autre méthode très utile est la méthode « text ».
X – coordonnée x en pixels
Y – coordonnée y en pixels
Text – une string contenant le texte à afficher.
Sur base de ces méthodes il est donc très aisé de construire notre classe boxplot .
Le framework raphaeljs peut-être télécharger ici
Et voici le code du boxplot:
function BoxPlot ( min, q1,q2,q3, max, mean, divTarget) {
this._divTarget=null;
this._name=name;
this._min=min;
this._q1=q1;
this._q2=q2;
this._q3=q3;
this._max=max;
this._mean=mean;
if (divTarget) this._divTarget=$(divTarget);
this.show=function () {
var sWidth=this._divTarget.style.width;
var sHeight=this._divTarget.style.height;
var iMaxX=sWidth.substring(0,sWidth.length-2); //this._divTarget.style.width.substring(1,;
var iMaxY=sHeight.substring(0,sHeight.length-2); //this._divTarget.style.height;
var q1_y=iMaxY*this._q1/this._max;
var q2_y=iMaxY*this._q2/this._max;
var q3_y=iMaxY*this._q3/this._max;
var mean_y=iMaxY*this._mean/this._max;
var canvas= Raphael(this._divTarget, sWidth, sHeight);
// top whisker
var ibx=0.20*iMaxX;
var iex=0.80*iMaxX;
canvas.path("M"+ibx+" "+iMaxY+" L "+iex+" "+iMaxY);
canvas.path("M"+ibx+" "+(iMaxY-1)+" L "+iex+" "+(iMaxY-1));
var imx=0.50*iMaxX;
// Box Plot
canvas.path("M"+imx+" "+iMaxY+" L "+imx+" "+(iMaxY-q1_y));
canvas.path("M 0 "+ (iMaxY-q1_y)+ " L "+iMaxX+" "+(iMaxY-q1_y));
canvas.path("M 0 "+ (iMaxY-q1_y)+ " L 0 "+(iMaxY-q2_y) );
canvas.path("M "+iMaxX+" "+ (iMaxY-q1_y)+ " L "+iMaxX+" "+(iMaxY-q2_y) );
canvas.path("M 0 "+ (iMaxY-q2_y) + " L "+iMaxX+" "+(iMaxY-q2_y) );
canvas.path("M 0 "+(iMaxY-q2_y)+" L 0 "+(iMaxY-q3_y) );
canvas.path("M "+iMaxX+" "+(iMaxY-q2_y) +" L "+iMaxX+" "+(iMaxY-q3_y));
canvas.path("M 0 "+(iMaxY-q3_y)+" L "+iMaxX+" "+(iMaxY-q3_y));
canvas.path("M "+imx+" "+(iMaxY-q3_y)+" L "+imx+" 0");
canvas.path("M "+ibx+ " 0"+" L "+iex+" 0");
canvas.path("M "+ibx+ " 1"+" L "+iex+" 1");
// Legend
canvas.text(16,4, ""+this._max);
canvas.text(16,(iMaxY-q3_y)+4, ""+this._q3);
canvas.text(16,(iMaxY-q2_y)+4, ""+this._q2);
canvas.text(16,(iMaxY-q1_y)-5, ""+this._q1 );
canvas.text(16,iMaxY-8, ""+this._min);
canvas.text(imx, (iMaxY-mean_y), "X");
}
}
lundi 26 septembre 2011
Javascript orienté objet
Contrairement aux apparences, Javascript permet de supporter des classes et des objets et par extension des frameworks complets peuvent-être écrits en Javascript (ex : prototypes, scriptacoulous, Ext Js, Raphaeljs…)
Je vais ici détailler une méthode classique de génération de classe en Javascript et donner une application directe à une classe permettant de générer des box-plots, graphique bien connu des statisticiens.
La création d’une classe en Javascript se fait simplement par la déclaration d’une fonction. Cette fonction utilise l’indentificateur « this ». Par défaut « this » pointe sur la fenêtre courante dans lequel le Javascript s’exécute. Toutefois si l’opérateur new est utilisé pour créer une instance de classe, this pointera sur cette instance plutôt que sur l’objet « window ».
Cet éclaricissement fait nous pouvons commencer à créer notre première classe :
function Boxplot ( min, q1,q2,q3, max, mean, divTarget) {
}
Vous me direz, ça ne ressemble pas vraiment à une classe mais à une bonn vieille function clasique de Javascript qui prend ,le minum, le quartile 25, la médiane, le quartile 75, le max et la moyenne de la distribution comme paramètre.
L’utilité du paramètre divTarget, très utile sera détaillé ultérieurement.
Ajoutons des membres et des méthodes à cette classe, pour se faire nous allons utiliser l’identificateur « this »
function Boxplot ( min, q1,q2,q3, max, mean, divTarget) {
this._min=min;
this._q1=q1;
this._q2=q2;
this._q3=q3;
...
}
Je vais créer autant de membres qu’il y a de paramètre dans mon constructeur et oui ici comme la classe est une fonction, son constructeur est d’office la fonction : Boxplot dans notre cas de figure.
J’utilise la notation _membre pour signifier que ce membre est privé, contrairement aux langages réellement orientés objet, Javascript ne dispose pas de restriction de visibilité. On prend donc cette convention venant de PERL pour signifier les éléments privés.
Il est intéressant d’avoir conçu une classe Boxplot toutefois si on ne peut pas l’afficher elle n’est pas très utile, nous allons donc ajouter une méthode à notre classe : show() qui permettra d’afficher le box-plot.
function Boxplot ( min, q1,q2,q3, max, mean, divTarget) {
this._min=min;
this._q1=q1;
this._q2=q2;
this._q3=q3;
...
this.show=function () {
… code de la fonction
}
}
Ici j’ai déclaré une fonction publique je n’indique pas d’underscore devant.
Concrètement comment cela va-t-il fonctionner ?
Je devrais réserver un emplacement où placer mon box-plot dans ma page web, typiquement, je vais définir un panel de type DIV qui contiendra mon résultat.
Ensuite je créer une instance de ma classe en lui passant les paramètres de la distribution que je veux boxplotter.
Concrètement ça nous donne ceci :
var boxplot = new BoxPlot(1,8.75,13,16.35,28,13.3,"test");
boxplot.show();
Test référant le panel DIV. Le résultat est donné en haut de page.
Dans le prochain billet je donnerai le détail de l’affichage du boxplot (le contenu dans la fonction show() ).
mercredi 21 septembre 2011
Calcul de taille d'échantillon
n= taille del'échantillon
N= taille de la population, cela implique que la taille de la population doit être connue, ce qui n'est pas toujours le cas!
Il faut savoir que cette formule est totalement empirique, inutile de trouver une démonstration mathématique permettant d'arriver à ce résultat, mais que malgré les mise en garde, elle est encore tès souvent utilisée.
L'étude suivante, illustre que si N>30 et que la distribution est normale, dans 90% des cas, la formule de la racine carrée +1 donnera une taille d'échantillon capable de donner un intervalle de 95% autours de la moyenne...