2015-08-08 11 views
7

plik zawiera:Tworzenie listy z pliku w Pythonie

1 19 15 36 23 18 39 
2 36 23 4 18 26 9 
3 35 6 16 11 

od tego chciałbym listy wyodrębnić w następujący sposób:

L = [1,19,15,36,23,18,19,2,36........... ect.] 

Co jest najbardziej skutecznym sposobem, aby to zrobić?

+0

Czy rozdzielono spacery/znaki nowej linii? –

Odpowiedz

5

Można użyć itertools.chain, dzieląc każdą linię i mapowanie do int:

from itertools import chain 
with open("in.txt") as f: 
    print(list((map(int,chain.from_iterable(line.split() for line in f))))) 
[1, 19, 15, 36, 23, 18, 39, 2, 36, 23, 4, 18, 26, 9, 3, 35, 6, 16, 11] 

Do stosowania python2 itertools.imap zamiast mapie. używając łańcucha z mapą i itertools.chain unika się natychmiastowego odczytu całego pliku do pamięci, co zrobi .read.

Niektóre czasy dla python3 na pliku taka sama jak wejścia * 1000:

In [5]: %%timeit 
with open("ints.txt","r") as f: 
    list(map(int,re.split(r"\s+",f.read()))) 
    ...: 
100 loops, best of 3: 8.55 ms per loop 

In [6]: %%timeit             
with open("ints.txt","r") as f: 
    list((map(int, chain.from_iterable(line.split() for line in f)))) 
    ...: 
100 loops, best of 3: 5.76 ms per loop 

In [7]: %%timeit 
...: with open("ints.txt","r") as f: 
...:  [int(i) for i in f.read().split()] 
...: 
100 loops, best of 3: 5.82 ms per loop 

Więc itertools pasuje do listy komp ale zużywa dużo mniej pamięci.

Dla python2:

In [3]: %%timeit             
with open("ints.txt","r") as f: 
    [int(i) for i in f.read().split()] 
    ...: 
100 loops, best of 3: 7.79 ms per loop 

In [4]: %%timeit             
with open("ints.txt","r") as f: 
    list(imap(int, chain.from_iterable(line.split() for line in f))) 
    ...: 
100 loops, best of 3: 8.03 ms per loop 

In [5]: %%timeit             
with open("ints.txt","r") as f: 
    list(imap(int,re.split(r"\s+",f.read()))) 
    ...: 
100 loops, best of 3: 10.6 ms per loop 

Lista komp jest nieznacznie szybciej, ale ponownie wykorzystuje więcej pamięci, jeśli chcieć czytać wszystko w pamięci z odczytu podzielić podejście IMAP jest ponownie najszybszy:

In [6]: %%timeit 
    ...: with open("ints.txt","r") as f: 
    ...:  list(imap(int, f.read().split())) 
    ...: 
100 loops, best of 3: 6.85 ms per loop 

samo dla python3 i mapy:

In [4]: %%timeit             
with open("ints.txt","r") as f: 
    list(map(int,f.read().split())) 
    ...: 
100 loops, best of 3: 4.41 ms per loop 

Więc jeśli prędkość jest wszystko, czego zależy użyj podejścia list(map(int,f.read().split())) lub list(imap(int,f.read().split())).
Jeśli pamięć również jest problemem, połącz ją z łańcuchem. Kolejną zaletą podejścia łańcuchowego, jeśli pamięć jest problemem, jest to, że jeśli przekazujesz ints do funkcji lub iterujesz, możesz bezpośrednio przekazać obiekt łańcucha, więc nie musisz w ogóle przechowywać wszystkich danych w pamięci.

ostatnia mała optymalizacja jest mapowanie str.split na obiekcie pliku:

In [5]: %%timeit 
with open("ints.txt", "r") as f: 
    list((map(int, chain.from_iterable(map(str.split, f))))) 
    ...: 
100 loops, best of 3: 5.32 ms per loop 
2
f=open("output.txt","r") 
import re 
print map(int,re.split(r"\s+",f.read())) 
f.close() 

Można użyć re.split który zwróci listę i map do int.

3
with open('yourfile.txt') as f: 
    your_list = f.read().split() 

Aby przesłać go do liczby całkowitej. Można użyć kompresji listy:

your_list = [int(i) for i in f.read().split()] 

Może to spowodować wyjątek, gdy nie można przesłać wartości.

+0

BTW: To podejście jest dobre dla małych i średnich plików. –

+0

@vks Domyślny podział dzieli na spacje i znaki nowej linii. Ale muszę przetestować '\ r' ... –

+0

W Pythonie 2 i 3:' >>> '1 \ r \ n2'.split() '→' [' 1 ',' 2 '] ' –

0

Możesz użyć re.findall.

import re 
with open(file) as f: 
    print map(int, re.findall(r'\d+', f.read())) 
1

Jeśli są w porządku z użyciem numpy bibliotekę, inny sposób byłoby użyć np.fromstring() dając pliku, .read() jako wejście do niego przykład -

import numpy as np 
with open('file.txt','r') as f: 
    lst = np.fromstring(f.read(),sep=' ',dtype=int) 

Pod koniec lst byłoby numpy tablicy , jeśli chcesz mieć listę Pythona, zawsze używaj tablicy 1D, a gdy podasz spację jako separator, zignoruje ona dodatkowe spacje. , które obejmują nowe linie.


Przykład/Demo -

In [39]: import numpy as np 

In [40]: with open('a.txt','r') as f: 
    ....:  lst = np.fromstring(f.read(),sep=' ',dtype=int) 
    ....: 

In [41]: lst 
Out[41]: 
array([ 1, 19, 15, 36, 23, 18, 39, 2, 36, 23, 4, 18, 26, 9, 3, 35, 6, 
     16, 11]) 

In [42]: list(lst) 
Out[42]: [1, 19, 15, 36, 23, 18, 39, 2, 36, 23, 4, 18, 26, 9, 3, 35, 6, 16, 11] 

Wyniki testów -

In [47]: def func1(): 
    ....:  with open('a.txt','r') as f: 
    ....:   lst = np.fromstring(f.read(),sep=' ',dtype=int) 
    ....:   return list(lst) 
    ....: 
In [37]: def func2(): 
    ....:  with open('a.txt','r') as f: 
    ....:   return list((map(int,chain.from_iterable(line.split() for line in f)))) 
    ....: 

In [54]: def func3(): 
    ....:  with open('a.txt','r') as f: 
    ....:   return np.fromstring(f.read(),sep=' ',dtype=int) 
    ....: 

In [55]: %timeit func3() 
10000 loops, best of 3: 183 µs per loop 

In [56]: %timeit func1() 
10000 loops, best of 3: 194 µs per loop 

In [57]: %timeit func2() 
10000 loops, best of 3: 212 µs per loop 

Jeśli są w porządku z numpy.ndarray (która nie różni się od listy), która byłaby szybciej.