jpcgandre
jpcgandre

Reputation: 1505

Loop thru a list and stop when the first string is found

I have a list and I want to extract to another list the data that exist between top_row and bottom_row. I know the top_row and also that the bottom_row corresponds to data[0] = last integer data (next row is made of strings, but there are also rows with integers which I'm not interested).

I've tried several things, but w/o success:

for row,data in enumerate(fileData):
    if row > row_elements: #top_row
        try:
            n = int(data[0])
            aux = True
        except:
            n = 0
        while aux: #until it finds the bottom_row
            elements.append(data)

The problem is that it never iterates the second row, if I replace while with if I get all rows which the first column is an integer.

fileData is like:

*Element, type=B31H
  1,   1,   2
  2,   2,   3
  .
  .
  .
 359, 374, 375
 360, 375, 376
*Elset, elset=PART-1-1_LEDGER-1-LIN-1-2-RAD-2__PICKEDSET2, generate

I'm only interested in rows with first column values equal to 1 to 360.

Many thanks!

Upvotes: 1

Views: 222

Answers (4)

John Zwinck
John Zwinck

Reputation: 249434

The code you've posted is confusing. For example, "aux" is a poorly-named variable. And the loop really wants to start with a specific element of the input, but it loops over everything until it finds the iteration it wants, turning what might be a constant-time operation into a linear one. Let's try rewriting it:

for record in fileData[row_elements:]: # skip first row_elements (might need +1?)
    try:
        int(record[0])
    except ValueError:
        break # found bottow_row, stop iterating
    elements.append(record)

Upvotes: 4

Joel Cornett
Joel Cornett

Reputation: 24788

Use a generator:

def isInteger(testInput):
    try: 
        int(testInput)
        return True
    except ValueError: return False

def integersOnly(fileData):
    element = fileData.next()
    while isInteger(element):
        yield element
        element = fileData.next()

Upvotes: 0

satoru
satoru

Reputation: 33225

Will this work?

for row, data in enumerate(fileData):
    if row > row_elements: #top_row
        try:
            n = int(data[0])
            elements.append(data)
        except ValueError:
            continue

Or what about:

elements = [int(data[0]) for data in fileData if data[0].isdigit()]

By the way, if you care to follow the convention of most python code, you can rename fileData to file_data.

Upvotes: 1

poke
poke

Reputation: 388103

If no exception is thrown in the try part, then you basically end up with an endless loop, given that aux will always be True.

I’m not perfectly sure what you are doing in your code, given the way the data looks isn’t clear and some things are not used (like n?), but in general, you can stop a running loop (both for and while loops) with the break statement:

for row, data in enumerate(fileData):
    if conditionToAbortTheLoop:
        break

So in your case, I would guess something like this would work:

for row, data in enumerate(fileData):
    if row > row_elements: # below `top_row`
        try:
            int(data[0])
        except ValueError:
            break # not an int value, `bottom_row` found

        # if we get here, we’re between the top- and bottom row.
        elements.append(data)

Upvotes: 2

Related Questions