Home > database >  Why does this list comprehension based on zip object does not work in subsequent loop iterations?
Why does this list comprehension based on zip object does not work in subsequent loop iterations?

Time:12-13

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)
  • Related