2017-05-22 2 views
0

J'ai un fichier maître qui contient certaines texte- nous allons dire-match de 2 cordes exactement, sauf dans des endroits où il y a une chaîne particulière en python

file contains x 
the image is of x type 
the user is admin 
the address is x 

et puis il y a 200 autres fichiers texte contenant des textes comme-

file contains xyz 
the image if of abc type 
the user is admin 
the address if pqrs 

Je dois faire correspondre ces fichiers. Le résultat sera vrai si les fichiers contiennent le texte exactement tel qu'il est dans le fichier maître, avec x étant différent pour chaque fichier, par exemple 'x' dans le master peut être n'importe quoi dans les autres fichiers et le résultat sera vrai.Que j'ai venir avec est

arr=master.split('\n') 
for file in files: 
    a=[] 
    file1=file.split('\n') 
    i=0 
    for line in arr: 
     line_list=line.split() 
     indx=line_list.index('x') 
     line_list1=line_list[:indx]+line_list[indx+1:] 
     st1=' '.join(line_list1) 
     file1_list=file1[i].split() 
     file1_list1=file1_list[:indx]+file1_list[indx+1:] 
     st2=' '.join(file1_list1) 
     if st1!=st2: 
      a.append(line) 
     i+=1 

qui est très inefficace. Existe-t-il un moyen de mapper les fichiers avec le fichier principal et de générer les différences dans un autre fichier?

Répondre

0

Je sais que ce n'est pas vraiment une solution, mais vous pouvez vérifier si le fichier est dans le même format en faisant somwthing comme:

if "the image is of" in var: 
    to do 

en vérifiant le reste des lignes

« fichier contient »

"l'utilisateur est"

"l'adresse est"

vous serez en mesure de peu validade si le fichier que vous vérifiez est valide

Vous pouvez vérifier ce lien pour en savoir plus sur cette « idée sous-chaîne »

Does Python have a string contains substring method?

+0

Merci Breno. Oui je peux valider les autres fichiers en utilisant ce qui précède mais même cela me demanderait d'écrire la condition if pour chaque ligne, mon fichier maître contient 100 lignes. Je pensais que ce serait mieux si je pouvais en quelque sorte mapper les 2 fichiers en ignorant la variable 'x' et générer les différences dans un autre fichier, un peu comme notepad ++ compare- mais en ignorant 'x'. – user2715898

+0

Je vois, je n'ai jamais expérimenté en utilisant regex, n'est-il pas utilisé pour des cas comme celui-ci? –

+0

Je n'ai jamais beaucoup utilisé regex non plus - je vais vérifier. Merci. – user2715898

0

Est-ce " universel "unique sur la ligne? Par exemple, si la clé est, en effet, x, êtes-vous sûr que x n'apparaît nulle part ailleurs dans la ligne? Ou le fichier maître pourrait avoir quelque chose comme

excluding x records and x axis values 

Si vous faire ont une clé unique ...

Pour chaque ligne, diviser le fichier maître sur votre clé x. Cela vous donne deux pièces pour la ligne, avant et arrière. Ensuite, vérifiez simplement si la ligne startswith la partie avant et endswith la partie arrière. Quelque chose comme

for line in arr: 
    front, back = line.split(x_key) 
    # grab next line in input file 
    ... 
    if line_list1.startswith(front) and 
     line_list1.endswith(back): 
     # process matching line 
    else: 
     # process non-matching line 

Voir documentation


MISE À JOUR PAR OP COMMENTAIRE

Tant que x est unique au sein de la ligne, vous pouvez facilement adapter ce.Comme vous le mentionnez dans votre commentaire, vous voulez quelque chose comme

if len(line) == len(line_list1): 
    if all(line[i] == line_list1[i] for i in len(line)): 
     # Found matching lines 
    else: 
     # Advance to the next line 
+0

Merci beaucoup pour cette prune. Il y a des blocs avec plusieurs 'x', donc il faudra suivre une approche différente pour ces blocs. Aussi, je suppose que la condition if est meilleure avec - si len (line) == len (line_list1) et line_list1.startswith (avant) et line_list1.enswith (retour): - il se peut qu'il y ait plus de variables dans entre. – user2715898

0

Voici une approche qui, selon moi, répond à vos besoins. Il vous permet également de spécifier si seul le même différence devrait être autorisée sur chaque ligne ou non (qui examinerait votre deuxième exemple de fichier comme ne correspondant pas):

MISE À JOUR: cela représente les lignes du maître et d'autres fichiers étant pas nécessairement dans le même ordre

from itertools import zip_longest 

def get_min_diff(master_lines, to_check): 
    min_diff = None 
    match_line = None 
    for ln, ml in enumerate(master_lines): 
     diff = [w for w, m in zip_longest(ml, to_check) if w != m] 
     n_diffs = len(diff) 
     if min_diff is None or n_diffs < min_diff: 
      min_diff = n_diffs 
      match_line = ln 

    return min_diff, diff, match_line 

def check_files(master, files): 
    # get lines to compare against 
    master_lines = [] 
    with open(master) as mstr: 
     for line in mstr: 
      master_lines.append(line.strip().split())  
    matches = [] 
    for f in files: 
     temp_master = list(master_lines) 
     diff_sizes = set() 
     diff_types = set() 
     with open(f) as checkfile: 
      for line in checkfile: 
       to_check = line.strip().split() 
       # find each place in current line where it differs from 
       # the corresponding line in the master file 
       min_diff, diff, match_index = get_min_diff(temp_master, to_check) 
       if min_diff <= 1: # acceptable number of differences 
        # remove corresponding line from master search space 
        # so we don't match the same master lines to multiple 
        # lines in a given test file 
        del temp_master[match_index] 
        # if it only differs in one place, keep track of what 
        # word was different for optional check later 
        if min_diff == 1: 
         diff_types.add(diff[0]) 
       diff_sizes.add(min_diff) 
      # if you want any file where the max number of differences 
      # per line was 1 
      if max(diff_sizes) == 1: 
       # consider a match if there is only one difference per line 
       matches.append(f) 
      # if you instead want each file to only 
      # be different by the same word on each line 
      #if len(diff_types) == 1: 
       #matches.append(f) 
    return matches 

J'ai fait quelques fichiers de test pour vérifier, en fonction de vos exemples fournis:

:::::::::::::: 
test1.txt 
:::::::::::::: 
file contains y 
the image is of y type 
the user is admin 
the address is y 
:::::::::::::: 
test2.txt 
:::::::::::::: 
file contains x 
the image is of x type 
the user is admin 
the address is x 
:::::::::::::: 
test3.txt 
:::::::::::::: 
file contains xyz 
the image is of abc type 
the user is admin 
the address is pqrs 
:::::::::::::: 
testmaster.txt 
:::::::::::::: 
file contains m 
the image is of m type 
the user is admin 
the address is m 
:::::::::::::: 
test_nomatch.txt 
:::::::::::::: 
file contains y and some other stuff 
the image is of y type unlike the other 
the user is bongo the clown 
the address is redacted 
:::::::::::::: 
test_scrambled.txt 
:::::::::::::: 
the image is of y type 
file contains y 
the address is y 
the user is admin 

Effectué, le code retourne au-dessus des fichiers corrects:

In: check_files('testmaster.txt', ['test1.txt', 'test2.txt', 'test3.txt', 'test_nomatch.txt', 'test_scrambled.txt']) 
Out: ['test1.txt', 'test2.txt', 'test3.txt', 'test_scrambled.txt'] 
+0

Merci pour cette approche Glarue. Une chose est qu'il n'est pas nécessaire que line1 dans master soit line1 dans notre checkfile, il se peut que line1 de master soit la ligne 4 de checkfile (mais nous pouvons être sûrs que line2 et line3 de checkfile sont n'est pas en maître). Ce que je pense est - si line1 de master n'est pas line1 de checkfile, nous vérifions les autres lignes de checkfile et si la ligne1 n'est pas présente n'importe où - nous l'ajoutons dans notre rapport. Ensuite, pour line2 de master, nous partons du point où line1 a cessé de correspondre dans checkfile. Faites-moi savoir si vous avez une meilleure approche. – user2715898

+0

@ user2715898 voir ma réponse mise à jour – glarue