2012-04-16 3 views
1

Я немного знаком с Python. У меня есть файл с информацией, которую мне нужно прочитать очень определенным образом. Ниже приведен пример ...Чтение в содержимом файлов в массивы

1 
6 
0.714285714286 
0 0 1.00000000000 
0 1 0.61356352337 
... 
-1 -1 0.00000000000 
0 0 5.13787636499 
0 1 0.97147643932 
... 
-1 -1 0.00000000000 
0 0 5.13787636499 
0 1 0.97147643932 
... 
-1 -1 0.00000000000 
0 0 0 0 5.13787636499 
0 0 0 1 0.97147643932 
.... 

Таким образом, каждый файл будет иметь эту структуру (с разделителями табуляции).

  • Первая строка должна считываться как переменная, так и вторая и третья строки.
  • Далее у нас есть четыре блока кода, разделенных -1 -1 0.0000000000. Каждый блок кода имеет длину 'n'. Первые два числа представляют позицию/местоположение, в которые 3-й номер в строке должен быть вставлен в массив. Отображаются только уникальные позиции (так что позиция 0 1 будет такой же, как 1 0, но эта информация не будет показана).
  • Примечание: 4-й блок кода имеет 4-индексное число.

Что мне нужно

  • Первые 3 строки читать как уникальные переменные
  • Каждый блок данных считывается в массив, используя первый 2 (или 4) столбец чисел, к которой индекс массива и третий столбец, как значение, вставленное в массив.
  • Показаны только уникальные элементы массива. Мне нужно зеркальное положение, которое должно быть заполнено надлежащим значением (значение 0 1 должно также отображаться в 1 0).
  • Последний блок должен быть вставлен в 4-мерный массив.
+4

Что вы уже пробовали? – yannis

+0

Я не пробовал ничего (отсутствие опыта работы с Python), следовательно, мой пост на SE. – LordStryker

ответ

3

я переписал код. Теперь это почти то, что вам нужно. Вам нужна только тонкая настройка.

Я решил оставить старый ответ - возможно, это тоже было бы полезно. Потому что новое полнофункциональное, и иногда может быть непонятным для понимания.

def the_function(filename): 
    """ 
    returns tuple of list of independent values and list of sparsed arrays as dicts 
    e.g. ([1,2,0.5], [{(0.0):1,(0,1):2},...]) 
    on fail prints the reason and returns None: 
    e.g. 'failed on text.txt: invalid literal for int() with base 10: '0.0', line: 5' 
    """ 

    # open file and read content 
    try: 
     with open(filename, "r") as f: 
      data_txt = [line.split() for line in f] 
    # no such file 
    except IOError, e: 
     print 'fail on open ' + str(e) 

    # try to get the first 3 variables 
    try: 
     vars =[int(data_txt[0][0]), int(data_txt[1][0]), float(data_txt[2][0])] 
    except ValueError,e: 
     print 'failed on '+filename+': '+str(e)+', somewhere on lines 1-3' 
     return 

    # now get arrays 
    arrays =[dict()] 
    for lineidx, item in enumerate(data_txt[3:]): 
     try: 
      # for 2d array data 
      if len(item) == 3: 
       i, j = map(int, item[:2]) 
       val = float(item[-1]) 
       # check for 'block separator' 
       if (i,j,val) == (-1,-1,0.0): 
        # make new array 
        arrays.append(dict()) 
       else: 
        # update last, existing 
        arrays[-1][(i,j)] = val 
      # almost the same for 4d array data 
      if len(item) == 5: 
       i, j, k, m = map(int, item[:4]) 
       val = float(item[-1]) 
       arrays[-1][(i,j,k,m)] = val 
     # if value is unparsable like '0.00' for int or 'text' 
     except ValueError,e: 
      print 'failed on '+filename+': '+str(e)+', line: '+str(lineidx+3) 
      return 
    return vars, arrays 
+0

Невероятно. Сейчас я настраиваю этот код. – LordStryker

+0

Я могу сопоставить float в позиции (i, j) в массиве, но не (j, i). Я попытался вставить 'array_ [-1] [(j, i)] = val' в оператор if/else, но мой массив не имеет двойного размера (21 элемент, а не 42). Есть предположения? – LordStryker

+0

Странно. Это должно сработать. Вы проверили опечатку? Случаи, где i = 0, j = 0? – akaRem

1

Для чтения строк из файла итеративно, вы можете использовать что-то вроде:

with open(filename, "r") as f: 
    var1 = int(f.next()) 
    var2 = int(f.next()) 
    var3 = float(f.next()) 
    for line in f: 
    do some stuff particular to the line we are on... 

Просто создать некоторые структуры данных вне цикла, и заполнить их в приведенном выше цикле. Для разделения строк на элементы, вы можете использовать:

>>> "spam ham".split() 
['spam', 'ham'] 

Я также думаю, что вы хотите взглянуть на numpy библиотек для datastructures массива, а также возможного SciPy библиотеки для анализа.

+3

лучше использовать 'с open (имя_файла,« r ») как f:' и поставить выражения в 'with' block – jamylak

+0

Отредактировав ответ, я думаю, что главным преимуществом является то, что' close' не нужно вызывать соединение с файлом. –

+2

Является ли дубликат открытым (имя файла, «r») ошибка редактирования? – Levon

2

Как я anderstand что вы просите ..

# read data from file into list 
parsed=[] 
with open(filename, "r") as f: 
    for line in f: 
     # # you can exclude separator here with such code (uncomment) (1) 
     # # be careful one zero more, one zero less and it wouldn work 
     # if line == '-1 -1 0.00000000000': 
     #  continue 
     parsed.append(line.split()) 

# a simpler version 
with open(filename, "r") as f: 
    # # you can exclude separator here with such code (uncomment, replace) (2) 
    # parsed = [line.split() for line in f if line != '-1 -1 0.00000000000'] 
    parsed = [line.split() for line in f] 

# at this point 'parsed' is a list of lists of strings. 
# [['1'],['6'],['0.714285714286'],['0', '0', '1.00000000000'],['0', '1', '0.61356352337'] .. ] 

# ALT 1 ------------------------------- 
# we do know the len of each data block 

# get the first 3 lines: 
head = parsed[:3] 

# get the body: 
body = parsed[3:-2] 

# get the last 2 lines: 
tail = parsed[-2:] 

# now you can do anything you want with your data 
# but remember to convert str to int or float 

# first3 as unique: 
unique0 = int(head[0][0]) 
unique1 = int(head[1][0]) 
unique2 = float(head[2][0]) 

# cast body: 
# check each item of body has 3 inner items 
is_correct = all(map(lambda item: len(item)==3, body)) 
# parse str and cast 
if is_correct: 
    for i, j, v in body: 
     # # you can exclude separator here (uncomment) (3) 
     # # * 1. is the same as float(1) 
     # if (i,j,v) == (0,0,1.): 
     #  # here we skip iteration for line w/ '-1 -1 0.0...' 
     #  # but you can place another code that will be executed 
     #  # at the point where block-termination lines appear 
     #  continue 

     some_body_cast_function(int(i), int(j), float(v)) 
else: 
    raise Exception('incorrect body') 


# cast tail 
# check each item of body has 5 inner items 
is_correct = all(map(lambda item: len(item)==5, tail)) 
# parse str and cast 
if is_correct: 
    for i, j, k, m, v in body: # 'l' is bad index, because similar to 1. 
     some_tail_cast_function(int(i), int(j), int(k), int(m), float(v)) 
else: 
    raise Exception('incorrect tail') 

# ALT 2 ----------------------------------- 
# we do NOT know the len of each data block 

# maybe we have some array? 
array = dict() # your array may be other type 

v1,v2,v2 = parsed[:3] 
unique0 = int(v1[0]) 
unique1 = int(v2[0]) 
unique2 = float(v3[0]) 

for item in parsed[3:]: 
    if len(item) == 3: 
     i,j,v = item 
     i = int(i) 
     j = int(j) 
     v = float(v) 

     # # yo can exclude separator here (uncomment) (4) 
     # # * 1. is the same as float(1) 
     # # logic is the same as in 3rd variant 
     # if (i,j,v) == (0,0,1.): 
     #  continue 

     # do your stuff 
     # for example, 
     array[(i,j)]=v 
     array[(j,i)]=v 

    elif len(item) ==5: 
     i, j, k, m, v = item 
     i = int(i) 
     j = int(j) 
     k = int(k) 
     m = int(m) 
     v = float(v) 

     # do your stuff 

    else: 
     raise Exception('unsupported') # or, maybe just 'pass' 
+0

Это почти то, что мне нужно. Я забыл явно упомянуть, что строки '-1 -1 0,00000' были просто строками-терминалами (итерация, если достигнет значения -1 ... end current array и запустит новый). Я думаю, что смогу настроить ваш пример, чтобы получить то, что мне нужно. Конечно, любая помощь всегда приветствуется. – LordStryker

+0

Добавлены некоторые вставки кода (4 варианта), где вы можете исключить «линии завершения блока» или обрабатывать их по мере необходимости. Надеюсь, тебе понравится! – akaRem

+0

Я ценю вашу дальнейшую помощь. У меня возникли проблемы с тем, что программа создавала новый массив каждый раз, когда был достигнут индикатор -1, а затем заполняем этот массив следующим блоком кода. Сейчас он сбрасывает все блоки кода длиной 3 элемента в один массив. – LordStryker

Смежные вопросы