Comparer les lignes de 2 fichiers text [Résolu]

Messages postés
76
Date d'inscription
mardi 28 juin 2005
Statut
Membre
Dernière intervention
21 avril 2010
- - Dernière réponse : Dezouille
Messages postés
76
Date d'inscription
mardi 28 juin 2005
Statut
Membre
Dernière intervention
21 avril 2010
- 16 août 2005 à 15:08
Bonjour,
J'aimerais comparer les lignes de deux fichiers text. Mes fichiers possedes des lignes avec dedans un numéro de factures. Chaque fichier possede plus de 10000 lignes. En faites je voudrais verifier si les numéros de factures du premier fichier text se trouve dans le deuxieme, si les numeros du 2eme se trouve dans le premier, et si dans le deuxieme il n'y a pas de doublons. Je ne sais pas si j'ai bien expliqué.
Merci de votre aide.
Afficher la suite 

11 réponses

Meilleure réponse
Messages postés
442
Date d'inscription
jeudi 4 avril 2002
Statut
Membre
Dernière intervention
11 août 2008
3
Merci
Oubli pas de creer les stringlist:
list1 := TStringList.Create();

Euh sinon les "°" il accepte le compilo ? Et si le fichier contiend plus de 10000 lignes ça risque pas de plomber la mémoire de les charger dans un stringlist ? il devrait etre possible de faire une lecture directement depuis le fichier, mais je croit que la méthode est légèrement plus compliquée.

neodelphi

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 120 internautes nous ont dit merci ce mois-ci

Commenter la réponse de neodelphi
Messages postés
1651
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
6
0
Merci
salut,

ouvre tes fichiers dans deux stringlist

de la première tu extrais les numeros de factures et tu verifie dans la seconde si le némero est present

tu dois faire 2 boucles imbriquées ça devrait donner quelque chose comme ça

list1.loadfromfile (nom du fichier 1 );//on charge les fichiers dans les listes

list2.loadfromfile (nom du fichier 2 );



for i:= 0 to list1.count-1 do/ / on recherche le n° de facture

begin

N°Fac: =copy(list1.items[i],x,y]);// je ne connais pas l'organisation de tes données

present:= false;

for j: =0 to list2.count-1 do //on recherche la présence dans la seconde liste

begin

if (pos( N°Fac,list2.items[j])<>0)then

if present then traitement du doublon else present: =true

end;

if not present then traitement pas de facture en liste2

end;
Commenter la réponse de jlen100
Messages postés
76
Date d'inscription
mardi 28 juin 2005
Statut
Membre
Dernière intervention
21 avril 2010
0
Merci
Merci pour ta reponse, en faite, si je comprend bien, on balaye a chaque fois toute la liste 2, tu me corrige si je me trompe. Car les listes ne sont pas trier. Se ne serais pas mieux de trier les liste sur les numeros de facture? J'aimerais que mon programme fasse une verification le plus rapidement possible.
Commenter la réponse de Dezouille
Messages postés
76
Date d'inscription
mardi 28 juin 2005
Statut
Membre
Dernière intervention
21 avril 2010
0
Merci
Je suis d'accord avec Neodelphi, je pense qu'il faudrais mieux faire un lecture direct, mais là je ne voit pas tellement comment faire, si quelqun pouvait m'aider la dessus, se serait gentil, merci.
Commenter la réponse de Dezouille
Messages postés
442
Date d'inscription
jeudi 4 avril 2002
Statut
Membre
Dernière intervention
11 août 2008
0
Merci
Je ne sais plus comment on fait, mais je pense que tu peut rechercher du coté des TFileStream (pas les TMemoryStream qui chargent en mémoire le contenu du fichier, ce que tu veux éviter).

Recherche sinon des sources sur le site je pense qu'il y en a pas mal.
voir exemple

neodelphi
Commenter la réponse de neodelphi
Messages postés
1651
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
6
0
Merci
salut neodelphi,

non le compilo n'accepte pas le '°' c'était juste pour facilité la lecture!!

pour la lecture directe il vaut mieux passer par l'ouverture d'un fichier texte normal

mais tu devras quand même charger la seconde liste tu peux toutefois alleger la mémoire en creant une liste de N°.

tu fais

var F1,F2:file;

buffer1,buffer2:string;

begin
list1 := TStringList.Create();

AssignFile(F1,FileName);

AssignFile(F2,FileName);


reset(F1);

reset(F2);

whille not eof(F2) do

begin


readln(F2,buffer2);

la tu extrait tes N° et du les ajoutes à list1: list1.append(n°);

end;

puis pour les boucles

while not eof (F1) do/ / on recherche le n° de facture

begin

readln(F1,buffer1)

N°Fac: =copy(buffer1);// je ne connais pas l'organisation de tes données

present:= false;

for j: =0 to list1.count-1 do //on recherche la présence dans la seconde liste

begin

if (pos( N°Fac,list2.items[j])<>0)then//nota on ne peut pas utiliser la fonction indexof qui ne retourne que la premiere occurence dommage !!

if present then traitement du doublon else present: =true

end;

if not present then traitement pas de facture en liste2

end;
Commenter la réponse de jlen100
Messages postés
1651
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
6
0
Merci
il y a une solution pour réduire la recherche au lieu d'utiliser une
variable string on peut utiliser une variable record et tu utilise des
pointeurs

type :

Spointeur:^Ppointeur;

Ppointeur:

record

numfac:string;

numligne:integer;

end;

var Plist2:Spoint;

dans la creation de la liste tu fais:

i:=0;// premier enregistrement;

whille not eof(F2) do

begin

new(Plist2);//tu crée une entrée;

readln(F2,buffer2);

la tu extrait tes N° -->

with Plist2 do

begin
numligne:=i;// tu mémorises la ligne;
numfac:=N°;

end;
//tu les ajoutes à list1:

list1.add(Plist2);

end;

ensuite quand tu as fais la recherche avant de sortir du traitement tu fais

dispose(Plist2);// pour liberer la memoire;

list1.delete(i);// tu supprimes l'entrée et tu diminue la longueur de la liste attention tu ne peux liberer les entrees que tu as parcouru toute la liste il faudra donc mémoriser les entree a supprimer

ainsi la liste est réduite aux seules lignes qui n'ont pas été traitées.
Commenter la réponse de jlen100
Messages postés
76
Date d'inscription
mardi 28 juin 2005
Statut
Membre
Dernière intervention
21 avril 2010
0
Merci
Ok merci, je vais essayer tous ça
Commenter la réponse de Dezouille
Messages postés
1651
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
6
0
Merci
c'est encore moi,

après avoir regardé j'ai trouvé le moyen d'utiliser indexof qui renvoie la prmier occurence trouvée

dans le recherche tu peux faire

while list2.indexof(N°Fac)<>-1 do

begin

j:= list2.indexof(N°Fac);

Plist2:=list2[i];//nota j'avais oublie l'affectattion: pas bien!!

if no t present then

begin

present: =true ;traitement de l'entree (tu as le N° de ligne dans Plist2^.numligne)

end else traitement du doublon;

dispose(Plist2);// pour liberer la memoire;

list1.delete(j);// tu supprimes l'entrée et tu diminues la longueur de la liste

end;

le programme parcourt ainsi la liste jusqu'à la fin et supprime les
occurences au fur et à mesure. inconvénient il reprend le test depuis
le début (bien que ce soit trasparent le traitement risque d'etre plus
long.

également dans la constitution de la liste j'ai oublié d'incrementer i qui restera à 0: pas facile de retrouver le N° de ligne!!!

et dans with Plist2^ sinon le compilateur doit renvoyer une erreur decidement ce n'est pas mon jour!!

pour info sur un PC cadencé entre 2 et 3GHz le temps de traitement pour
10000 entrée devrait se situer au alentour de 10s non compris le
traitement de l'info (~10ns par test) pour la derniere solution cela
dvrait tourner au alentour de 15 a 20s
Commenter la réponse de jlen100
Messages postés
1651
Date d'inscription
samedi 10 juillet 2004
Statut
Membre
Dernière intervention
25 juillet 2014
6
0
Merci
tu peux encore améliorer la performance de l'ensemble en vérifiant s'il y a des doublons à la création de lits2 tu fais :

if list2.indexof(N°)<>-1 then traitement du doublon;

dans ce cas le traitement ce réduira a

while not eof (F1) do// on recherche le n° de facture

begin
readln(F1,buffer1)
N°Fac:= copy (buffer1);

j: =list2.indexof(N°Fac); // recherche de l'entrée

Plist2: = list2[i];

if j =-1 then traitement pas de facture en liste2

else

begin

traitement;

dispose(Plist2);// pour liberer la memoire;

list1.delete(j);// tu supprimes l'entrée et tu diminues la longueur de la liste

end;

end;

En séparant ainsi les 2 traitements on gagne d'une part en clarté et
d'autre part en efficacité psuique la liste à traitée ne contient plus
que des données valides

bonne prog
Commenter la réponse de jlen100
Messages postés
76
Date d'inscription
mardi 28 juin 2005
Statut
Membre
Dernière intervention
21 avril 2010
0
Merci
Merci beaucoup pour toutes ses infos precieuses, ça a l'aire pas mal du tout
Commenter la réponse de Dezouille