Reputation: 396
I have written some code, and to try and grasp the concept of list comprehensions, I am trying to convert some of the code into list comprehensions.
I have a nested for loop:
with (Input) as searchfile:
for line in searchfile:
if '*' in line:
ID = line[2:13]
IDstr = ID.strip()
print IDstr
hit = line
for i, x in enumerate(hit):
if x=='*':
position.append(i)
print position
I have made the first part of the code into a list comprehension as such:
ID = [line[2:13].strip() for line in Input if '*' in line]
print ID
This works fine. I have tried to do some of the next, but it is not working as intended. How do I make several list comprehensions after each other. The "Hit = …"-part below works fine, if it is the first list comprehension, but not if it is the second. The same with the above - it seems to work only, if it is the first. Why is this?
Hit = [line for line in Input if '*' in line]
print Hit
Positions = [(i, x) for i, x in enumerate(Hit) if x == '*']
print Positions
Upvotes: 1
Views: 130
Reputation: 82949
it seems to work only, if it is the first. Why is this?
This is because file
objects -- input
in your case -- are iterators, i.e. they are exhausted once you iterated them once. In your for loop this is not a problem, because you are iterating the file just once for both ID
and position
. If you want to use two list comprehensions like this, you either have to open the file anew for the second one, or read the lines from the file into a list, and use that list in the list comprehensions.
Also note that your positions
list comprehension is wrong, as it enumerates the Hit
list, and not each of the elements in the list, as was the case in your loop.
You could try like this (not tested):
# first, get the lines with '*' just once, cached as a list
star_lines = [line for line in input if '*' in line]
# now get the IDs using those cached lines
ids = [line[2:13].strip() for line in star_lines]
# for the positions we need a nested list comprehension
positions = [i for line in star_lines for i, x in enumerate(line) if x == '*']
That nested list comprehension is about equivalent to this nested loop:
positions = []
for line in star_lines:
for i, x in enumerate(line):
if x == '*':
posiitons.append(i)
Basically, you just "flatten" that block of code and put the thing to be appended to the front.
Upvotes: 2