Возвращает диапазон индексов, которые соответствуют заданному условию - PullRequest
1 голос
/ 23 марта 2020

У меня есть большие файлы данных, отформатированные следующим образом:

    1 M * 0.86
    2 S * 0.81
    3 M * 0.68
    4 S * 0.53
    5 T . 0.40
    6 S . 0.34
    7 T . 0.25
    8 E . 0.36
    9 V . 0.32
   10 I . 0.26
   11 A . 0.17
   12 H . 0.15
   13 H . 0.12
   14 W . 0.14
   15 A . 0.16
   16 F . 0.13
   17 A . 0.12
   18 I . 0.12
   19 F . 0.22
   20 L . 0.44
   21 I * 0.68
   22 V * 0.79
   23 A * 0.88
   24 I * 0.88
   25 G * 0.89
   26 L * 0.88
   27 C * 0.81
   28 C * 0.82
   29 L * 0.79
   30 M * 0.80
   31 L * 0.74
   32 V * 0.72
   33 G * 0.62

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

Итак, для этого примера желаемый результат будет выглядеть так:

1-4,21-33 13

Спасибо за любую помощь!

Ответы [ 2 ]

1 голос
/ 23 марта 2020

Есть несколько способов сделать это.

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

После того, как вы это сделали, вы можете попробовать следующее:

  • Итерация по каждой строке файла:
    • Если в строке есть * :
    • Затем:
      • сохранить индекс (это отправная точка)
      • читать строки, пока в строке есть "*"
      • keep индекс (это конечная точка)
    • читать следующую строку

In Python:

# your file path
filepath = 'test.txt'

with open(filepath) as fp:
    line = fp.readline()
    # Count the line index
    cnt = 1

    # Output storing deb and end index
    output = []

    # While there are lines in the file (e.g. the end of file not reached)
    while line:
        # Check if the current line has a "*"
        if "*" in line:
            # If yes, keep the count value, it's the starting point
            deb = cnt
            # Iterate while there are "*" in line
            while "*" in line:
                cnt += 1
                line = fp.readline()
            # END while (e.g end of file or there is no "*" in the line
            # Add the starting index and end index to the output 
            output.append({"deb" : deb, "end": cnt - 1})

        # Read next line
        cnt += 1
        line = fp.readline()

    print(output)
    # [{'deb': 1, 'end': 4}, {'deb': 21, 'end': 33}]
0 голосов
/ 23 марта 2020

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

def find_ranges(fn):
    with open(fn) as f:
        start = None
        for line_no, line in enumerate(f):
            if start is None:
                if '*' in line:
                    start = line_no + 1 # start of a range
            elif '*' not in line:
                yield [start, line_no]  # seen end of range
                start = None
        if start is not None: # end of file without seeing end of a range
            yield [start, line_no + 1]

ranges = [range for range in find_ranges('test.txt')]
max_range = max(ranges, key = lambda x: x[1] - x[0]) # largest range seen
print(ranges, max_range[1] - max_range[0] + 1)

Отпечатки:

[[1, 4], [21, 33]] 13

Конечно, вы можете отформатировать диапазоны так, как вам wi sh.

Тот же алгоритм без использования генератора:

def find_ranges(fn):
    ranges = []
    with open(fn) as f:
        start = None
        for line_no, line in enumerate(f):
            if start is None:
                if '*' in line:
                    start = line_no + 1 # start of a range
            elif '*' not in line:
                ranges.append([start, line_no]) # end of a range
                start = None
        if start is not None: # end of file without seeing end of a range
            ranges.append([start, line_no + 1])
        max_range = max(ranges, key = lambda x: x[1] - x[0])
        return ranges, max_range[1] - max_range[0] + 1

ranges, max_range = find_ranges('test.txt')
print(ranges, max_range)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...