Comparer les lignes de 2 fichiers text

Résolu
Dezouille Messages postés 75 Date d'inscription mardi 28 juin 2005 Statut Membre Dernière intervention 21 avril 2010 - 16 août 2005 à 09:40
Dezouille Messages postés 75 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.
A voir également:

11 réponses

neodelphi Messages postés 442 Date d'inscription jeudi 4 avril 2002 Statut Membre Dernière intervention 11 août 2008
16 août 2005 à 10:59
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
3
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
16 août 2005 à 10:39
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;
0
Dezouille Messages postés 75 Date d'inscription mardi 28 juin 2005 Statut Membre Dernière intervention 21 avril 2010
16 août 2005 à 10:58
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.
0
Dezouille Messages postés 75 Date d'inscription mardi 28 juin 2005 Statut Membre Dernière intervention 21 avril 2010
16 août 2005 à 11:11
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.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
neodelphi Messages postés 442 Date d'inscription jeudi 4 avril 2002 Statut Membre Dernière intervention 11 août 2008
16 août 2005 à 11:16
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
0
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
16 août 2005 à 11:39
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;
0
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
16 août 2005 à 12:08
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.
0
Dezouille Messages postés 75 Date d'inscription mardi 28 juin 2005 Statut Membre Dernière intervention 21 avril 2010
16 août 2005 à 13:31
Ok merci, je vais essayer tous ça
0
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
16 août 2005 à 14:24
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
0
jlen100 Messages postés 1606 Date d'inscription samedi 10 juillet 2004 Statut Membre Dernière intervention 25 juillet 2014 13
16 août 2005 à 14:48
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
0
Dezouille Messages postés 75 Date d'inscription mardi 28 juin 2005 Statut Membre Dernière intervention 21 avril 2010
16 août 2005 à 15:08
Merci beaucoup pour toutes ses infos precieuses, ça a l'aire pas mal du tout
0
Rejoignez-nous