Question: I have large data files formatted as follows:

```
    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

```

What I'm trying to figure out how to do is loop through each line in the file and, if the line contains an asterisk, begin finding a subsequent range that satisfies this condition. Additionally it would be nice to output the largest range in a file. 

So for this example, the desired output would look like:

```
1-4,21-33 13

```

Thanks for any assistance!

Answer: 
There are several way to perform this. 

One solution is to read the file line by line. I advise you to have a look at this very good [tutorial](https://stackabuse.com/read-a-file-line-by-line-in-python/) on how to read file. 

Once you did it, you can try the following:

* Iterate over each line of the file:
	+ If there is an `*` in the line:
	+ Then:
		- keep the index (this a starting point)
		- read the lines while there is an "\*" in the line
		- keep the index (this a end point)
	+ read next line

In Python:

```py
# 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}]

```
Since people are running to answer, this one uses a generator to generate ranges:

```
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)

```

Prints:

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

```

You can, of course, format the ranges anyway you wish.

The same algorithm without using a generator:

```
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)

```