2010-04-21 16 views
5

Jestem całkiem nowe do programowania Python i byłby wdzięczny za pomoc na problem mam ...Python: Znajdowanie i zamienianie liczb <1 w pliku tekstowym

Zasadniczo mam wiele plików tekstowych, które zawierają wartości prędkości jako sposób:

0.259515E + 03 0.235095E + 03 0.208262E + 03 0.230223E + 03 0.267333E + 03 0.217889E + 03 0.156233E + 03 0.144876E + 03 0.136187E + 03 0.137865E + 00

itp. dla wielu linii ...

Co muszę zrobić, to przekonwertować wszystkie wartości w pliku tekstowym, które są mniej niż 1 (np. 0,137865E + 00 powyżej) do arbitralnej wartości 0,100000E + 01. O ile proste zastąpienie określonych wartości metodą "replace()" i pętlą while, jak to zrobić, jeśli chcesz zastąpić zakres?

dzięki

Odpowiedz

7

myślę kiedy zaczynają programowanie warto zobaczyć kilka przykładów; i zakładam, że najpierw próbowałeś tego problemu samemu!

Oto break-down, w jaki sposób można podejść do tego:

contents='0.259515E+03 0.235095E+03 0.208262E+03 0.230223E+03 0.267333E+03 0.217889E+03 0.156233E+03 0.144876E+03 0.136187E+03 0.137865E+00' 

W split method prace nad strunami. Zwraca listę ciągów. Domyślnie, to dzieli się na białe znaki:

string_numbers=contents.split() 
print(string_numbers) 
# ['0.259515E+03', '0.235095E+03', '0.208262E+03', '0.230223E+03', '0.267333E+03', '0.217889E+03', '0.156233E+03', '0.144876E+03', '0.136187E+03', '0.137865E+00'] 

map command dotyczy pierwszego argumentu (funkcja float) do każdego z elementów jej drugiego argumentu (lista string_numbers). Funkcja float konwertuje każdy ciąg znaków na obiekt zmiennoprzecinkowy.

float_numbers=map(float,string_numbers) 
print(float_numbers) 
# [259.51499999999999, 235.095, 208.262, 230.22300000000001, 267.33300000000003, 217.88900000000001, 156.233, 144.876, 136.18700000000001, 0.13786499999999999] 

Można użyć list comprehension przetwarzać listy, konwersji liczb mniej niż 1 do numeru 1. conditional expression(1 if num<1 else num) równa 1 gdy num jest mniejsza niż 1, w przeciwnym razie, to równa num.

processed_numbers=[(1 if num<1 else num) for num in float_numbers] 
print(processed_numbers) 
# [259.51499999999999, 235.095, 208.262, 230.22300000000001, 267.33300000000003, 217.88900000000001, 156.233, 144.876, 136.18700000000001, 1] 

To jest to samo, wszystko w jednym wierszu:

processed_numbers=[(1 if num<1 else num) for num in map(float,contents.split())] 

wygenerować ciąg Spośród elementów processed_numbers, można użyć str.join method:

comma_separated_string=', '.join(map(str,processed_numbers)) 
# '259.515, 235.095, 208.262, 230.223, 267.333, 217.889, 156.233, 144.876, 136.187, 1' 
+0

to jest świetne. Spędziłem dzisiaj wieki zastanawiając się, dlaczego wyrażenie warunkowe nie działa, a następnie zdałem sobie sprawę, że muszę uaktualnić wersję 2.4 – hjp

4

typowa technika byłoby:

  • linia pliku do odczytu przez linię
  • Podział każda linia w liście ciągów
  • przekonwertować każdy ciąg do pływaka
  • porównania przerobiona wartość z 1
  • w razie potrzeby wymień
  • odpisać do nowego pliku

Ponieważ nie widzę konieczności jeszcze żadnego kodu, mam nadzieję, że będzie to dobry początek

+0

dzięki, miałem świadomość, że muszą one zostać przekształcone do pływaków, ale nie wiedział o liniach podziału. – hjp

3
def float_filter(input): 
    for number in input.split(): 
     if float(number) < 1.0: 
      yield "0.100000E+01" 
     else: 
      yield number 

input = "0.259515E+03 0.235095E+03 0.208262E+03 0.230223E+03 0.267333E+03 0.217889E+03 0.156233E+03 0.144876E+03 0.136187E+03 0.137865E+00" 
print " ".join(float_filter(input)) 
0

You może używać wyrażeń regularnych do analizowania łańcucha. Zakładam, że mantysa nigdy nie jest większa niż 1 (tzn. Zaczyna się od 0). Oznacza to, że aby liczba była mniejsza niż 1, wykładnik musi mieć wartość 0 lub ujemną. Następujące wyrażenie regularne dopasowuje "0", ".", Nieograniczoną liczbę cyfr dziesiętnych (co najmniej 1), "E" i "+00" lub "-" i dwie cyfry dziesiętne.

0\.\d+E(-\d\d|\+00) 

Zakładając, że plik wczytywane do zmiennej „tekst”, można użyć wyrażenia regularnego z następującego kodu Pythona:

result = re.sub(r"0\.\d*E(-\d\d|\+00)", "0.100000E+01", text) 

EDIT: Właśnie sobie sprawę, że opis nie ogranicza prawidłowy zakres numerów wejściowych do liczb dodatnich. Liczby ujemne mogą być dopasowane następującym regexp:

-0\.\d+E[-+]\d\d 

To może być zmieniane z pierwszego używając (wzorzec1 | pattern2) składni co skutkuje następującym kodzie Pythona:

result = re.sub(r"(0\.\d+E(-\d\d|\+00)|-0\.\d+E[-+]\d\d)", "0.100000E+00", subject) 

Także jeśli jest szansa, że ​​wykładnik przekroczy 99, wyrażenie regularne może być dalej modyfikowane przez dodanie znaku "+" po wzorcach "\ d \ d". Pozwala to na dopasowanie cyfr kończących się na dwie LUB więcej cyfr.

0

Mam skrypt działający tak, jak chcę teraz ... dzięki ludziom. Podczas pisania listy do nowego pliku użyłem metody replace, aby pozbyć się nawiasów i przecinków - czy jest prostszy sposób?

ftext = open("C:\\Users\\hhp06\\Desktop\\out.grd", "r") 
otext = open("C:\\Users\\hhp06\\Desktop\\out2.grd", "w+") 

for line in ftext: 
    stringnum = line.split() 
    floatnum = map(float, stringnum) 
    procnum = [(1.0 if num<1 else num) for num in floatnum] 
    stringproc = str(procnum) 
    s = (stringproc).replace(",", " ").replace("[", " ").replace("]", "") 
    otext.writelines(s + "\n") 
otext.close() 
+0

Hi hjp. Lepiej dodać komentarz, aby zapytać osobę bezpośrednio lub opublikuj nowe pytanie. W ten sposób więcej osób to zauważy. Ale, aby odpowiedzieć na twoje pytanie, zdecydowanie nie chcesz używać 'replace' do tego zadania. Spróbuj 's = ',' .join (map (str, procnum))'. Zobacz http://docs.python.org/library/stdtypes.html#str.join – unutbu

3
import numpy as np 

a = np.genfromtxt('file.txt') # read file 
a[a<1] = 0.1     # replace 
np.savetxt('converted.txt', a) # save to file 
Powiązane problemy