Bonjour à tous,
Je bosse actuellement sur un script qui permet de convertir un fichier de format A vers un fichier de format B (pour faire simple).
A un moment, je dois trier les lignes du fichier A car c’est nécessaire dans la suite du traitement.
Seulement, je souhaite complexifier un peu le tri.
Un peu d’explication :
le fichier d’entrée contient n lignes, chaque champ (ou valeur peu importe) est séparé par un pipe ‘|’.
la première ligne du fichier contient le nom des colonnes indiquant ce que sont les champs.
exemple :
account|investissement1|adresse1|adresse2|adresse3|pays|codepostal
123456|FundAfrica|Bank Money|34 rue de la mairie|etage 4|France|76500|
98765|FundAfrica|Bank Money|34 rue de la mairie|etage 4|France|76500|
…
Mon but est de sécuriser le tri en ne triant par sur un numéro de colonne fixe, mais sur un numéro qui aura été calculé dynamiquement en fonction de la position de la colonne cherchée dans le fichier. CAD que si je fais un tri sur la colonne ‘pays’, je chercherais d’abord l’indice du champ ‘pays’ dans la première ligne du fichier. Cela permet, dans le cas d’un ajout de colonne aléatoire de ne pas avoir à modifier le code car ce dernier saura où elle se trouve lors de l’exécution.
Là où ça se corse, c’est que je dois trier suivant 3 colonnes.
J’ai déjà une solution qui fonctionne mais le temps de traitement est très long, environ 12s pour 4 Mo de données.
my @indexcolonne = getIndexColonne( 'account' ,'adresse1' , 'pays' , @tabIn );
my @sorttab = sort {
(split /\|/ , $a)[indexcolonne[0]] cmp (split /\|/ ,$b)[indexcolonne[0]] ||
(split /\|/ ,$a)[indexcolonne[1]] cmp (split /\|/ ,$b)[indexcolonne[1]] ||
(split /\|/ ,$a)[indexcolonne[2]] cmp (split /\|/ , $b)[indexcolonne[2]]
} @tabIn;
une autre solution est d’utiliser le sort BLOCK avec l’appel à une sous fonction, en ayant auparavant splitté chaque ligne du tableau tabIn de sorte à avoir une matrice. Cette méthode est beaucoup plus rapide ( 1,5seconde en gros) mais il reste toujours les 3 ‘cmp’.
Et c’est ce que je veux éviter. Je n’aime pas écrire en dur indexcolonne[qqch] dans le code, je voudrais rendre celà dynamique. Par exemple :
sub sortData{
my (@a , @b) = @_;
//il doit manqueer une déreference..., mais bref
my $res = 0;
foreach (@indexcolonne){
$res = $res || ($a[$_] cmp $b[$_]);
}
return $rex;
}
my @indexcolonne; #variable globale, doit pouvoir être passé en paramètre
main{
...
my @sorttab = sort sortData @tabIn;
...}
mon problème est sur la variable $res et le traitment du résultat ‘cmp’ qui sont faux car le tri est mal réalisé.
J’aurais donc voulu savoir si vous avez des suggestions de corrections, voire des algos pour résoudre ce problème tout en gardant à l’esprit que la position des colonnes et le nombre de colonnes utilisées pour le tri peuvent être variables.