I have a piece of code where I want to filter out a part of a list in consecutive loop iterations:
def calculate_delays(flash_time_stamps, sample_time_stamps, sample_values, threshold):
delays = []
first_thresh_cross_time_stamps = []
samples = zip(sample_time_stamps, sample_values)
# For each flash find the first sample that crosses the chosen threshold
# and calculate the difference between the corresponding timestamps
for flash_time_stamp in flash_time_stamps:
first_cross_thresh_time_stamp = -1
# Ignore samples that occured before the flash
samples_filtered = [s for s in samples if s[0] >= flash_time_stamp] # ---COMPREHENSION IS HERE---
for sample in samples_filtered:
if sample[1] < threshold:
first_cross_thresh_time_stamp = sample[0]
break
# Save
first_thresh_cross_time_stamps.append(first_cross_thresh_time_stamp)
delays.append(first_cross_thresh_time_stamp - flash_time_stamp)
return first_thresh_cross_time_stamps, delays
In the first iteration, the code works as expected, but in the subsequent iterations, the list comprehension returns an empty list. I know that this should not be the case based on the data I'm passing. Also, the following code works as expected:
def calculate_delays(flash_time_stamps, sample_time_stamps, sample_values, threshold):
delays = []
first_thresh_cross_time_stamps = []
samples = zip(sample_time_stamps, sample_values)
# For each flash find the first sample that crosses the chosen threshold
# and calculate the difference between the corresponding timestamps
for flash_time_stamp in flash_time_stamps:
first_cross_thresh_time_stamp = -1
# Ignore samples that occured before the flash
for sample in samples:
if sample[0] < flash_time_stamp: # ---CHANGE HERE---
continue
if sample[1] < threshold:
first_cross_thresh_time_stamp = sample[0]
break
# Save
first_thresh_cross_time_stamps.append(first_cross_thresh_time_stamp)
delays.append(first_cross_thresh_time_stamp - flash_time_stamp)
return first_thresh_cross_time_stamps, delays
What am I doing wrong here?
CodePudding user response:
when you iterate over zip object it pops all of it data so second time this is an empty list samples_filtered = [s for s in samples if s[0] >= flash_time_stamp]
so you can zip data on the go like this
samples_filtered = [s for s in zip(sample_time_stamps, sample_values) if s[0] >= flash_time_stamp]
happy coding.
CodePudding user response:
I wouldn't even use a list comprehension here, the second snippet would be more efficient since you're not creating a list unnecessarily if the first elements make you break the loop early on.
You could just use next and replace the entire for loop altogether
first_cross_thresh_time_stamp = next(
(s[0] for s in samples if s[0] >= flash_time_stamp and s[1] < threshold),
-1
)
first_thresh_cross_time_stamps.append(first_cross_thresh_time_stamp)