domingo, 13 de dezembro de 2015

Ficheiros (I)

Suponha que anda à procura num ficheiro de texto de um dado padrão. Como resolver o problema? Se pensar um pouco chegará à conclusão que vai ter que ler o ficheiro e analisar a cadeia de caracteres para determinar se o padrão o corre ou não. Podemos ler o ficheiro todo de uma vez, linha a linha ou todas as linhas (neste caso na forma de uma lista de linhas). Vejamos as diferentes soluções:
def wally_0(ficheiro,padrao):
    """wally está no ficheiro?"""
    with open(ficheiro,'r',encoding='utf-8') as f_ent:
        texto = f_ent.read()
        if padrao in texto:
            return True
        return False



def wally_1(ficheiro,padrao):
    """wally está no ficheiro?"""
    with open(ficheiro,'r',encoding='utf-8') as f_ent:
        for linha in f_ent:
            if padrao in linha:
                return True
        return False

    
def wally_11(ficheiro,padrao):
    """wally está no ficheiro?"""
    with open(ficheiro,'r',encoding='utf-8') as f_ent:
        texto = f_ent.readlines()
        for linha in texto:
            if padrao in linha:
                return True
        return False 

Suponhamos agora que a pergunta muda ligeiramente, e nos pedem para dizer não apenas se o padrão existe, mas também em que linha existe. Uma vez mais, uma breve reflexão leva-nos a concluir que ler todo o ficheiro de uma só vez não é agora adequado. Também ler todas as linhas não nos parece a melhor ideia: afinal mal encontremos o padrão podemos abandonar o programa e não precisamos de guardar na memória todos as linhas do ficheiro, que podem ser em número muito elevado. Como fazer? Essa uma resposta.
def wally_2(ficheiro,padrao):
    """em que linha está wally  no ficheiro?"""
    with open(ficheiro,'r',encoding='utf-8') as f_ent:
        for i,linha in enumerate(f_ent):
            if padrao in linha:
                return i+1
        return -1 
como se observa no código acima, usamos a função enumerate para nos resolver a dificuldade de ler as linhas e saber o seu número. E se agora nos disserem que se pretendem as linhas de todas as ocorrências? Hum,…, para isso precisamos de um contentor onde guardar a informação que vamos recolhendo por análise do ficheiro linha a linha.
def wally_3(ficheiro,padrao):
    """em que linhas está wally  no ficheiro?"""
    with open(ficheiro,'r',encoding='utf-8') as f_ent:
        num_lin = []
        for i,linha in enumerate(f_ent):
            if padrao in linha:
                num_lin.append(i+1)
        return num_lin 
Não param de mudar o que nos pedem: passou a ser a linha e a posição dentro da linha. Para resolver lá nos temos que socorrer dos métodos conhecidos sobre cadeias de caracteres:
def wally_4(ficheiro,padrao):
    """em que linha e posição na linha está wally?"""
    with open(ficheiro,'r',encoding='utf-8') as f_ent:
        for i,linha in enumerate(f_ent):
            pos = linha.find(padrao)
            if pos != -1:
                return i+1,pos
        return -1,-1
Como se pode ver o método find foi a nossa salvação. E este problema ainda mas para todas as ocorrências?
def wally_5(ficheiro,padrao):
    """em que linhas e posições nas linhas está wally?"""
    with open(ficheiro,'r',encoding='utf-8') as f_ent:
        num_pos_lin = []
        for i,linha in enumerate(f_ent):
            pos = linha.find(padrao)
            if pos != -1:
                num_pos_lin.append((i+1,pos))
        return num_pos_lin 
E se …. A sua imaginação é o limite. Tente perceber as alternativas e o modo como ficheiros, cadeias de caracteres e listas estão ligados entre si.

Sem comentários:

Enviar um comentário