2012-08-03 14 views
5

Quindi quello che voglio fare sembra relativamente semplice, ma per la vita di me, proprio non riesco a capirlo. Ho un file .txt comeElenco di stringhe a numeri interi mantenendo un formato in python

4 2 
6 5 1 
9 4 5 

E voglio le proprie informazioni siano disponibili a me in questo modo (cioè non ho bisogno di scrivere un nuovo file .txt a meno che non sarebbe stato necessario.) ...

3 1 
5 4 0 
8 3 4 

o, 1 viene sottratto da ogni numero ma la formattazione rimane la stessa. Non ci sarà mai un numero maggiore di 1 nell'originale, quindi i negativi non saranno possibili. L'intero mal di testa è dovuto alla conversione dell'indicizzazione per iniziare con 0 anziché 1. Ciò che può complicare le cose è che il file viene stampato originali come

['4 2 /n','6 5 1 /n', '9 4 5 /n'] 

quello che ho fatto

Bene suo un miscuglio di cose che ho differentfound su StackOverflow, ma penso che ho intenzione su di esso nel modo più macchinoso possibile. E this non aveva senso quando ho realizzato che .. anche se può essere sulla stessa pista con la questione con spazi ..

origianl = open(file, 'r') 
for line in original.readlines(): 
    newline = line.replace(" \n","") 
    finalWithStrings.append(newline) 

finalWithIntegers = [map(int,x) for x in finalWithStrings] 
finalWithIntegers[:] = [x-1 for x in finalWithIntegers] 

mio processo di pensiero è stato, ho bisogno di rimuovere il "/ n" e per convertire queste stringhe in numeri interi in modo da poter sottrarre 1 da loro. E in qualche modo mantenere la formattazione. È importante che la formattazione sia la stessa poiché ogni riga contiene informazioni sulla riga indicizzata in modo simile di un altro file. Non voglio vedere "/ n" nel risultato finale (o nell'istruzione di stampa) ma voglio comunque che inizi l'effetto di una nuova riga. Il codice sopra tuttavia, non funzionerà per due ragioni (che io sappia).

int(n[:]) genera un errore poiché non gli piacciono gli spazi e quando inserisco un valore (diciamo 0) li, quindi il codice stampa il primo numero su ciascuna delle linee e sottrae uno .. e mette tutto su una riga.

[3, 5, 8] 

Così, sembra ridondante di stipulare un ritorno a capo e devono gettare un'altra, ma ho bisogno di mantenere la formattazione, così come hanno un modo per ottenere tutti i numeri!

Questa, inoltre, non ha funzionato:

for line in original.readlines(): 
    newline = line.replace(" \n","") 
    finalWithStrings.append(newline) 

finalWithIntegers = [map(int,x) for x in finalWithStrings] 
finalWithIntegers[:] = [x-1 for x in finalWithIntegers]  

ma invece di un'uscita sbagliata che fosse un errore:

ValueError:invalid literal for int() with base 10:'' 

Qualcuno ha tutte le idee su quello che sto facendo male qui e come risolvere questo? Sto lavorando con Python 2.6 e sono un principiante.

risposta

9
with open("original_filename") as original: 
    for line in original: 
     #if you just want the line as integers: 
     integers = [ int(i) - 1 for i in line.split() ] 
     #do something with integers here ... 

     #if you want to write a new file, use the code below: 
     #new_line = " ".join([ str(int(i) - 1) for i in line.split() ]) 
     #newfile.write(new_line + '\n') 

Ho aperto il file in un gestore di contesto nell'esempio sopra perché è una buona pratica (dalla versione 2.5). Il gestore del contesto si assicura che il file sia chiuso correttamente quando si esce da quel contesto.

EDIT

Sembra che si potrebbe essere cercando di creare una lista 2D ...Per fare questo, qualcosa di simile a questo dovrebbe funzionare:

data = [] 
with open("original_filename") as original: 
    for line in original: 
     integers = [ int(i) - 1 for i in line.split() ] 
     data.append(integers) 

O, se si preferisce il 1-liner (io no):

with open("original_filename") as original: 
    data = [ [int(i) for i in line.split()] for line in original ] 

Ora, se si stampa:

for lst in data: 
    print (lst) # [3, 1] 
        # [5, 4, 0] 
        # [8, 3, 4] 
+0

Perfetto, questo è esattamente quello che stavo cercando! Grazie per la modifica .. era più specifico di ciò di cui avevo bisogno. – Ason

+0

@Ason - Nessun problema. Ho riletto il tuo post un po 'più attentamente e ho trovato la frase che diceva che non ti serviva in un nuovo file a meno che non fosse il modo più semplice per farlo. Quindi, ho aggiornato. – mgilson

+0

+1 Apprezzo il tempo che hai impiegato per rispondere! – Ason

4

Ecco un modo abbastanza semplice per eseguire ciò utilizzando le espressioni regolari. Il vantaggio è che la formattazione è garantito per rimanere esattamente lo stesso, perché andrà a sostituire i numeri a posto senza toccare nessuna delle spazio bianco:

import re 

def sub_one_repl(match): 
    return str(int(match.group(0))-1) 

for line in original.readlines(): 
    newline = re.sub(r'\d+', sub_one_repl, line).rstrip('\n') 
+0

Grazie mille per la tua risposta! Non ho molta familiarità con le espressioni regolari, quindi dovrò selezionare una risposta diversa in quanto è più facile da capire e implementare .. ma +1 per aiutare i futuri visitatori! – Ason

+0

Ottima idea, anche se penso che tu intenda "match.group' e non" m.group ". Inoltre, si potrebbe voler rendere 'sub_one_repl' un po 'più sicuro (cioè se la regex non riesce a far corrispondere il .group causerà un'eccezione) o semplicemente fare un lambda. Potresti farlo anche come elenco comp o espressione del generatore: '(re.sub (r '\ d +', lambda m: str (int (m.gruppo (0)) - 1), riga) per riga nell'originale .readlines()) ' –

+1

@AdamParkin - Grazie, originariamente avevo' m' come argomento e ho dimenticato di aggiornare la funzione. 'sub_one_repl' verrà chiamato solo per le partite riuscite, che saranno sempre tutte cifre, quindi dovrebbe essere sicuro così com'è.Una linea è un'opzione ma sposterei ancora il 'lambda' al di fuori di esso in modo da non ricreare la funzione su ogni iterazione. –

0

Prova questo:

with open(filepath) as f: 
    for line in f: 
     print " ".join([str(int(i)-1) for i in line.split()]) 

Speranza che aiuta

+0

Hai ragione. Risposta aggiornata – inspectorG4dget

2

Un altro modo è quello di utilizzare il modulo csv e la lista di comprensione:

from csv import reader 

data = [[int(j) - 1 for j in i] for i in reader(open("your_file"), delimiter=' ')] 

Per esempio, utilizza i tuoi dati:

[[3, 1], [5, 4, 0], [8, 3, 4]] 
Problemi correlati