Miglior codice di lettura dei dati in un ciclo [chiuso]

2

Quale soluzione per il mio piccolo problema considereresti uno stile migliore? C'è un'altra opzione migliore che mi manca?

La logica è semplice: elaborare i dati da un'origine fino a ottenere il token END .

Ho un paio di idee imperfette:

line = read_from_source()
while line != "END":
    process(line)
    line = read_from_source()

In realtà sto chiamando read_from_source() due volte quando la descrizione del linguaggio naturale del problema la chiama una volta. Potenziale bug di manutenzione quando qualcuno cambia un posto e dimentica l'altro.

while True:
    line = read_from_source()
    if line == "EOF": break
    process(line)

In qualche modo non mi piace perché la condizione del ciclo non si distingue chiaramente dal codice quando lo si guarda.

while line = read_from_source() != "END":
    process(line)

Conciso, ma trovo difficile fare raed quando gli operatori di assegnazione e uguaglianza si trovano sulla stessa linea.

    
posta Kuba 08.03.2017 - 15:27
fonte

6 risposte

2

Puoi anche fare una pausa.

while True:
    line = read_from_source()
    if line == 'END':
        break
    process(line)

Questo non è insolito in Python. Mentre a molti non piacerebbe lo stile e si sentisse a disagio con la parte while True , preferisco non leggere due posti. Potresti avvolgerlo come un generatore:

def lines_from_source(source):
    while True:
        line = read_from_source(source)
        if line == 'END':
            break
        yield line

E poi fai:

for line in lines_from_source(my_source):
    process(line)
    
risposta data 08.03.2017 - 15:58
fonte
1

Separa il concetto di "essere alla fine del file" da "leggere i dati da un file"

var fileStream = File.Open(filename);
while(!fileStream.EOF)
{
    var line = fileStream.ReadLine();
    process(line);
}

versione per un servizio

var serviceWrapper= new ServiceWrapper(service);
while(!serviceWrapper.IsAtEndOfSection)
{
    var line = serviceWrapper.ReadLine();
    process(line);
}

O davvero, se hai dati complessi dovresti deserializzare su un oggetto

Class Data
{
    List<Section> Sections;
}

Class Section
{
    list<string> Lines;
}
    
risposta data 08.03.2017 - 15:33
fonte
1

Leggi in un ciclo e se è la fine, interrompi il ciclo.

while True:
    line = read_from_source()
    if line == "EOF":
        break
    process_the_line()

Sostituisci True con qualche altra condizione se prevedi che l'origine si interrompa prima di "EOF"

    
risposta data 08.03.2017 - 15:55
fonte
0

Non hai familiarità con la sintassi di Python, ma ti verrà l'idea

var line = "";
while (line != "END")
{
    var line = fileStream.ReadLine();
    if (line != "END")
    {
        process(line);
    }
}

Ora, lo svantaggio di questo metodo è che hai due assegni per line != "END" L'alternativa potrebbe essere quella di creare un ciclo infinito e uscirne fuori quando la riga == "END". Meno carina, ma più efficiente. La soluzione più carina sarebbe quella di modificare il metodo di processo per gestire correttamente la stringa "END", nel qual caso non è necessario avere un controllo all'interno del ciclo.

    
risposta data 08.03.2017 - 15:56
fonte
0

Potresti rendere più chiara la seconda opzione:

doneReading = false    
while not doneReading:
    line = read_from_source()
    if line == "EOF":
        doneReading=true;
    else:
        process(line)

Ora la tua condizione ha un nome, può gestire una logica più complessa se ne hai bisogno. Inoltre, elimina un break non necessario, quindi va bene;)

La tua prima opzione non è poi così male, ma capisco che non ti piace chiamare read_from_source() in due posti diversi. La terza opzione è un po 'difficile da leggere, con il multiplo = nella stessa istruzione, eviterei quello stile quando possibile.

    
risposta data 08.03.2017 - 16:22
fonte
0

Non scrivere loop, i loop sono già scritti per te! Usali.

from itertools import takewhile, count

legit_line = lambda line: line != 'END'
result = [process(line) 
          for line in takewhile(legit_line, (read_from_source() for _ in count()))]

Questo è, ovviamente, un po 'di estremismo, ma sembra solo strano perché generare una sequenza infinita di chiamate read_from_source non è molto naturale in Python. Puoi utilizzare un ciclo esplicito per questo, tuttavia, ancora prendendo in considerazione il controllo:

def all_lines():
  while True:
    yield read_from_source()

for line in takewhile(legit_line, all_lines):
  # Here come only non-END lines again.
    
risposta data 08.03.2017 - 16:37
fonte

Leggi altre domande sui tag