Используя Python3 для поиска строки в файле, добавьте результаты в следующих строках в массив, прежде чем останавливаться на следующей строке

#python #python-3.x

#python #python-3.x

Вопрос:

Я использую Python 3 для обработки файла результатов. Структура файла представляет собой комбинацию строковых идентификаторов, за которыми следуют списки целочисленных значений в этом формате:

 ENERGY_BOUNDS 
  1.964033E 07  1.733253E 07  1.491825E 07  1.384031E 07  1.161834E 07  1.000000E 07  8.187308E 06  6.703200E 06
  6.065307E 06  5.488116E 06  4.493290E 06  3.678794E 06  3.011942E 06  2.465970E 06  2.231302E 06  2.018965E 06
EIGENVALUE 
  1.219034E 00
  

В этом файле может быть 50 различных наборов данных с уникальными идентификаторами. Что я хочу сделать, это написать код, который будет искать определенный идентификатор (например, ENERGY_BOUNDS ), затем считывать следующие значения в список, останавливаясь на следующем идентификаторе (в данном случае СОБСТВЕННОЕ ЗНАЧЕНИЕ). Затем мне нужно иметь возможность манипулировать списком (находить его длину, печатать его значения и т. Д.).

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

 def read_data_from_file(file_name, identifier):

    list_of_results = [] # Create list_of_results to put results in for future manipulation
    
    # Open the file in read only mode
    with open(file_name, 'r') as read_obj:

        # Read all lines in the file one by one
        for line in read_obj:

            # For each line, check if line contains the string
            if identifier in line:

                # If yes, read the next line
                nextValue = next(line)
                list_of_results.append(nextValue.rstrip())

    return list_of_results
  

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

Ответ №1:

Ниже приведен простой и проверенный ответ.

Вы допускаете две ошибки

  1. line это строка, а не итератор, поэтому это next(line) приводит к ошибке.
  2. Вы просто читаете одну строку после того, как идентификатор был найден, в то время как вам нужно продолжать чтение до тех пор, пока не появится другой идентификатор.

Ниже приведен код после небольшой модификации вашего кода. Это также проверено на ваших данных

 def read_data_from_file(file_name, identifier):
    with open(file_name, 'r') as read_obj:
        list_of_results = []
            # Read all lines in the file one by one
        for line in read_obj:

            # For each line, check if line contains the string
            if identifier in line:
                # If yes, read the next line
                nextValue = next(read_obj)
                while(not nextValue.strip().isalpha()): #keep on reading untill next identifier appears
                    
                    list_of_results.extend(nextValue.split())
                    nextValue = next(read_obj)
        print(list_of_results)

  

Комментарии:

1. Спасибо! Одна небольшая проблема — когда я запускаю это, я получаю ‘name’list_of_results’ is not defined’ когда дело доходит до окончательного оператора печати?

2. Он также считывает каждую строку как отдельную запись в list_of_results , тогда как мне нужно, чтобы каждое числовое значение в строке было разделено?

3. Исправьте это. list_of_results записано вне области действия функции. Это была ошибка отступа

4. Отредактировал ее. Просто разделите строку чисел и добавьте ее к предыдущему list использованию extend

5. Я попробовал новую версию, теперь она разбивает каждый отдельный символ на отдельную запись. В списке ENERGY_GROUPS list_of_results должно быть шестнадцать записей, по одной для каждого из чисел? Большое спасибо за вашу помощь!

Ответ №2:

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

 def read_data_from_file(file_name, identifier):

    list_of_results = [] # Create list_of_results to put results in for future manipulation
    identifier_found = False
    
    # Open the file in read only mode
    with open(file_name, 'r') as read_obj:

        # Read all lines in the file one by one
        for line in read_obj:

            # For each line, check if line contains the string
            if identifier in line:
                identifier_found = True
            elif identifier_found:
                if line.strip().isalpha(): # Next identifier reached, exit loop
                    break

                list_of_results  = line.split() # Add values to result

    return list_of_results
  

Комментарии:

1. Этот ответ такой же, как и предложенный пользователем Planman1717

2. Но я ответил на вопрос перед ним

Ответ №3:

Используйте логические значения, continue , и break !

Попробуйте реализовать логику следующим образом:

  • Задайте логическое значение (я буду использовать in_range ) в False
  • Просмотрите строки и посмотрите, соответствуют ли они идентификатору.
    • Если это произойдет, установите логическое значение в True и continue
    • Если это не так, continue
  • Если логическое значение равно False И строка начинается с пробела: continue
  • Если логическое значение равно True И строка начинается с пробела: добавьте строку в список.
  • Если логическое значение равно True И строка не начинается с пробела: break .

Это завершает процесс поиска после запуска нового идентификатора.

Комментарии:

1. Почему никто не использует continue или break ?

Ответ №4:

Другие 2 ответа уже полезны. Вот мой метод, если вам нужно что-то еще. С комментариями для объяснения. Если вы не хотите использовать end_identifier, вы можете использовать .isAlpha(), который проверяет, содержит ли строка только буквы.

 def read_data_from_file(file_name, start_identifier, end_identifier):

    list_of_results = []

    with open(file_name, 'r') as read_obj:
        start_identifier_reached = False  # variable to check if we reached the needed identifier_reached
        for line in read_obj:
            if start_identifier in line:
                start_identifier_reached = True  # now we reached the identifier
                continue  # We go back to the start so we dont write the identifier into the list
            if start_identifier_reached and (end_identifier not in line):  # Put the values into the list until we reach the end_identifier
                list_of_results.append(line.rstrip())
            else:
                return list_of_results