IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Comparaison de gros fichiers triés


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Femme Profil pro
    Ingénieur d'étude et de développement en bioinformatique en recherche d'emploi
    Inscrit en
    Mars 2012
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'étude et de développement en bioinformatique en recherche d'emploi
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2012
    Messages : 69
    Par défaut Comparaison de gros fichiers triés
    Bonjour,
    Je voudrais comparer deux fichiers contenant une liste complète et pour le second une liste partielle. Ces deux fichiers sont triés. J'aimerais une lecture simultanée des deux fichiers. Pour ça je compare la 1ere ligne du fichier 1 avec le fichier 2 :
    -Si elles sont identiques j'imprime la ligne du fichier 1 et 1 pour indiquer sa présence
    -Si elles sont différentes, je compare les 2 chaînes de caractères (elles sont triées). Si la ligne2 est inférieure a la ligne1 je compare la ligne1 avec la ligne2 suivante sinon j'imprime la ligne1 suivis d'un 0 pour indiquer son absence.
    J'ai deja commencer a regarder comment faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    #!/usr/bin/perl 
    use strict;
    use warnings;
    use Getopt::Long;
     
    my ($all,$TopHat,$T);
     
     
    GetOptions(	"all:s" => \$all,
    		"TopHat:s" => \$TopHat);
     
    if (!defined $all) {
    	die "Error : missing all file\n";
    }
    if (!defined $TopHat) {
    	die "Error : missing TopHat file\n";
     
    #Les trois fichiers
    my $fic1 = "$all";
    my $fic2 = "$TopHat";
     
    #Pour la lecture des lignes
    my $ligne1;
    my $ligne2;
     
    #Pour la lecture du contenu des lignes
    my $contenu1;
    my $contenu2;
     
    #Pour l'ouverture des lignes
    open(FIC1,$fic1);
    open(FIC2,$fic2);
     
    #Tant qu'il y a des lignes dans les fichiers
    while (my $ligne1 = <FIC1>) {
    	chomp($ligne1);
    	while (my $ligne2 = <FIC2>) {
    	chomp($ligne2);
    	if ($ligne1 eq $ligne2){
    		print "$ligne1 1";
    		} elsif ($ligne1 lt $ligne2){
    			print "$ligne1  0";
    		}
    	}
    	}
    }
    Mais cela ne focntionne pas.
    Quelqu'un saurait il m'aider?
    Merci d'avance

  2. #2
    Membre actif
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration

    Informations forums :
    Inscription : Décembre 2012
    Messages : 43
    Par défaut
    ça ne fonctionne pas car tu utilises une boucle while pour lire ton deuxième fichier.
    En fait, pour le première ligne du fichier 1 tu parcours tout le fichier 2. Quand tu passes à la seconde ligne du fichier 1, je pense que le fichier 2 est déjà lu (hypothès à vérifier), et donc il n'y à plus rien à lire.

    inspire toi de ce post : http://www.developpez.net/forums/d65...s/#post3848355

  3. #3
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Billets dans le blog
    1
    Par défaut
    Voici un exemple d'algo de base pour lire deux fichiers triés en parallèle:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    while (my $ligne1 = <FIC1>) {
    	my $ligne2 = <FIC2>;
    	if ($ligne2 gt $ligne1) {
    		# faire ce qu'il y a éventuellement à faire si ligne2 > ligne1
    		next; # aller à la ligne suivante du fichier 1
    	}
    	while ($ligne2 lt $ligne1) {
    		# faire ce qu'il y a éventuellement à faire si ligne2 < ligne1
    		$ligne2 = <FIC2>;
    	}
    	if ($ligne2 eq $ligne1) {
    		# faire ce qu'il y a a faire si les lignes sont égales
    	}
    }
    Je l'ai écrit vite fait et pas testé, il y a peut-être un bug ici ou là, , mais tu as l'idée de base de l'algo:

    - je lis FIC1 tant que ligne 1 est + petite que ligne 2 (et fait les autres choses éventuelles à faire dans ce cas)
    - je lis FIC2 tant que ligne 2 est plus petite que ligne 1 (et fait les autres choses éventuelles à faire dans ce cas)
    - je fais ce que j'ai à faire quand ligne 1 eq ligne 2.

  4. #4
    Membre confirmé
    Femme Profil pro
    Ingénieur d'étude et de développement en bioinformatique en recherche d'emploi
    Inscrit en
    Mars 2012
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'étude et de développement en bioinformatique en recherche d'emploi
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2012
    Messages : 69
    Par défaut
    Merci
    Mais j'ai toujours un pb avec cette ligne de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while ($ligne2 lt $ligne1) {
    		# faire ce qu'il y a éventuellement à faire si ligne2 < ligne1
    		$ligne2 = <FIC2>;
    car j'ai les comparaisons suivantes :
    SRR167674.1 SRR167674.10
    SRR167674.10 SRR167674.10000000
    SRR167674.100 SRR167674.1000003
    SRR167674.1000 SRR167674.1000004
    SRR167674.10000 SRR167674.1000007
    SRR167674.100000 SRR167674.1000009
    SRR167674.10000000 SRR167674.100001
    SRR167674.10000000 SRR167674.1000012

  5. #5
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Billets dans le blog
    1
    Par défaut
    Je ne donnais que l'algorithme de base pour lire en parallèle deux fichiers triés et trouver les lignes communes et les orphelins d'un côté ou de l'autre.

    L'utilisation de "lt" est juste un exemple, si ta comparaison est plus complexe, à toi de la mettre en oeuvre. Là, tu ne donnes pas d'information sur les règles de comparaison à employer.

    A priori, la clé de comparaison doit être la même que la clé de tri utilisée précédemment.

  6. #6
    Membre confirmé
    Femme Profil pro
    Ingénieur d'étude et de développement en bioinformatique en recherche d'emploi
    Inscrit en
    Mars 2012
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'étude et de développement en bioinformatique en recherche d'emploi
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2012
    Messages : 69
    Par défaut
    La comparaison est bonne mais lorsque cette comparaison est effectuée, il faudrait que j'aille a a la ligne suivante du fichier 2. Et je ne sais comment le faire.

  7. #7
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Billets dans le blog
    1
    Par défaut
    C'est en principe ce que font les lignes 7 à 9 de mon algo: lire les lignes du fichier 2 tant qu'elles sont "en retard" sur le fichier 1.

    Il faudrait de vrais fichiers pour tester, mais il me semble que l'algo doit fonctionner correctement.

    A noter que je n'ai donné que la construction de base de l'algorithme, il faudrait au minimum ajouter un test pour vérifier si $ligne2 est défini pour éviter des warnings intempestifs.

    EDIT: en fait, tu as raison, il y a un bug dans l'algo. Pourtant, je fais assez souvent ce genre de choses au boulot. Je regarde pour donner une version correcte.

  8. #8
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Billets dans le blog
    1
    Par défaut
    Donc, il y avait des anomalies dans l'algo simplifié présenté précédemment.

    Voici une version correcte et testée. Elle compare deux fichiers comprenant chacun un nombre par ligne. Le fichier doubles.txt contient les nombres 2, 4, 6, 8, 10, ..., 58, 60. Le fichier triples.txt contient 3, 6, 9, 12, 15, ..., 57, 60.

    Pour générer ces fichiers de test à la ligne de commande Unix ou Linux:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    perl -e 'print $_ * 2, "\n" foreach (1..30);' > doubles.txt
    perl -e 'print $_ * 3, "\n" foreach (1..20);' > triples.txt
    Et voici le code du programme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    #!/usr/bin/perl
     
    use strict;
    use warnings;
     
    open my $FIC1, "<", "doubles.txt" or die "$!";
    open my $FIC2, "<", "triples.txt" or die "$!";
     
    my (@communs, @orphelins1, @orphelins2);
     
    my $ligne2 = "-1"; # valeur impossible mais définie
    while (my $ligne1 = <$FIC1>) {
    	chomp $ligne1;
    	if ($ligne2 == $ligne1) {
    		push @communs, $ligne1 ; # faire ce qu'il y a a faire si les lignes sont égales
    		next;
    	}
    	last unless defined ($ligne2 = <$FIC2>);
    	chomp $ligne2;
    	while ($ligne2 > $ligne1) {
    		push @orphelins1, $ligne1; # faire ce qu'il y a éventuellement à faire si ligne2 > ligne1
    		$ligne1 = <$FIC1>;
    		chomp $ligne1;
    	}
    	push @orphelins1, $ligne1 if $ligne1 > $ligne2;
    	while ($ligne2 < $ligne1) {
    		push @orphelins2, $ligne2; # faire ce qu'il y a éventuellement à faire si ligne2 < ligne1
    		$ligne2 = <$FIC2>;
    		last unless defined $ligne2;
    		chomp $ligne2
    	}
    }
     
    print "Valeurs communes:\n";
    print "$_ " foreach @communs;
    print "\nOrphelins1:\n";
    print "$_ " foreach @orphelins1;
    print "\nOrphelins2:\n";
    print "$_ " foreach @orphelins2;
    close $FIC1; close $FIC2;
    Ce qui imprime:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ perl parallel_read.pl
    Valeurs communes:
    6 12 18 24 30 36 42 48 54 60
    Orphelins1:
    2 4 8 10 14 16 20 22 26 28 32 34 38 40 44 46 50 52 56 58
    Orphelins2:
    3 9 15 21 27 33 39 45 51 57

  9. #9
    Membre confirmé
    Femme Profil pro
    Ingénieur d'étude et de développement en bioinformatique en recherche d'emploi
    Inscrit en
    Mars 2012
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'étude et de développement en bioinformatique en recherche d'emploi
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2012
    Messages : 69
    Par défaut
    Merci c'est déjà beaucoup mieux, je l'ai adapté a mes données mais encore un petit probleme persiste.
    Quand on arrive à l'étape :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	while ($ligne2 > $ligne1) {
    		push @orphelins1, $ligne1; # faire ce qu'il y a éventuellement à faire si ligne2 > ligne1
    		$ligne1 = <$FIC1>;
    		chomp $ligne1;
    	}
    je compare mes deux listes
    SRR167674.1 SRR167674.10
    SRR167674.10 SRR167674.10000000
    SRR167674.100 SRR167674.1000003
    SRR167674.1000 SRR167674.1000004
    SRR167674.10000 SRR167674.1000007

    je compare 1 et 10 et comme 1<10 on entre dans la boucle ci-dessus.Mais avec ce script j'ai les comparaisons suivantes :
    SRR167674.1 et SRR167674.10
    SRR167674.100 et SRR167674.10000000
    et je n'ai pas la comparaison SRR167674.10 et SRR167674.10. Donc quand on fait l'étape ci-dessus. Est il possible d'effectuer cette comparaison?
    Merci

  10. #10
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Billets dans le blog
    1
    Par défaut
    Tu ne nous a rien dit sur la façon dont tu voulais comparer SRR167674.1 et SRR167674.10, je ne peux pas deviner; je ne sais même pas si ces expressions sont supposées être égales ou non. S'il s'agit juste de retirer les 0 décimaux en trop pour dire que les deux expressions ci-dessus sont équivalentes, une petite expression régulière en plus fera l'affaire, du genre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ligne =~ s/0+$//; # retire les 0 finaux
    ou

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ligne =~ s/(\w+^.\d+)0+$\$1/; # retire les 0 finaux s'ils sont précédés par des lettres ou des chiffres, un point décimal et des chiffres
    L'autre solution consiste à supprimer les lettres en début de ligne et de ne garder pour la comparaison que les chiffres, pour faire une comparaison numérique. Dans ce cas, la comparaison numérique (==) devrait trouver que les nombres 167674.1 et 167674.10 sont égaux.

    Cette second solution est sans doute meilleure, car Perl fera probablement lui-même les conversions dont tu as besoin.

    Donne plus d'informations sur tes fichiers en entrée et sur tes règles de comparaison.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Peut-on lire des gros fichiers(100k) avec "TClientSocke
    Par Fred LEM dans le forum C++Builder
    Réponses: 3
    Dernier message: 20/12/2004, 14h41
  2. Optimisation de la lecture de tres gros fichiers
    Par Lydie dans le forum C++Builder
    Réponses: 4
    Dernier message: 12/07/2004, 14h09
  3. [JDOM] Gestion "gros fichiers"
    Par Haazheel dans le forum Format d'échange (XML, JSON...)
    Réponses: 10
    Dernier message: 17/10/2003, 13h42
  4. Un langage pour lire, traiter et écrire de gros fichiers
    Par March' dans le forum Langages de programmation
    Réponses: 19
    Dernier message: 07/04/2003, 15h26
  5. XML DOM et gros fichiers
    Par Manu_Just dans le forum APIs
    Réponses: 4
    Dernier message: 28/03/2003, 09h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo