Search code examples
pythonlistdatetimetuplesabsolute-value

How can I use the python map() function to handle a list of tuples?


I currently have two lists and a working script that when given an element from list_a, finds all datetimes from list_b that are within 30 minutes. The community helped me with it in a previous question.

I replaced one of the lists with a list of tuples and have been trying to reconcile that in the script -- I'll explain some of the modifications I tried to make down below.

# Old Set of Two Lists
list_a = ["10:26:42", "8:55:43", "7:34:11"]
list_b = ["10:49:20", "8:51:10", "10:34:35", "8:39:47", "7:11:49", "7:42:10"]

# Previous Output
10:26:42 is within 30m of 10:49:20, 10:34:35
08:55:43 is within 30m of 08:51:10, 08:39:47
07:34:11 is within 30m of 07:11:49, 07:42:10
# Old List and New List of Tuples
my_flights = ["10:26:42", "8:55:43", "7:34:11"]
alt_flights = [("10:49:20", "Frontier"), ("8:51:10", "Southwest"), ("10:34:35", "Jet Blue"), ("8:39:47", "Delta"), ("7:11:49", "Spirit"), ("7:42:10", "American"]

# Desired Output
10:26:42 is within 30m of Frontier, Jet Blue at 10:49:20, 10:34:35
10:26:42 is within 30m of Southwest, Delta at 08:51:10, 08:39:47
10:26:42 is within 30m of Spirit, American at 07:11:49, 07:42:10

The working script for the old set of two lists is below, what I'm trying to do is (1) replace list_a with my_flights (2) replace list_b with alt_flights and (3) use the names in alt_flights with my output!

def str2time(s):
    h,m,s = map(int, s.split(':'))
    return datetime.timedelta(hours=h, minutes=m, seconds

z = datetime.datetime(1900,1,1)

for a in map(str2time, list_a):
    start = f'{z+a:%H:%M:%S} is within 30m of'

    for b in map(str2time, list_b):
        if abs(a-b).total_seconds() <= 1800:
            print(f'{start} {z+b:%H:%M:%S}', end='')
            start = ','

    if start == ',':
        print()

Attempted Modifications: I thought I could change list_b into for b in map(str2time, alt_flights[0][0]) and reference alt_flights[0][1] later to pull out the airline name, but that would throw an error with str2time(). Then I thought I could make a check underneath if abs(a-b).total_seconds() <= 1800: that would check if b in alt_flights which would grab the current airline name value of list_b[0][1]. But, both of those failed.


Solution

  • Instead of mapping the times in alt_flights before the loop, it might be easier to read if you pass the time data to str2time during printing. If you replace

    for b in map(str2time, list_b):
        if abs(a-b).total_seconds() <= 1800:
            print(f'{start} {z+b:%H:%M:%S}', end='')
    

    with

    for time, airline in alt_flights:
        if abs(a - str2time(time)).total_seconds() <= 1800:
            print(f"{start} {str2time(time)} {airline}", end='')
    

    the code will work as expected.

    The full second iteration:

    for a in map(str2time, my_flights):
        start = f'{z+a:%H:%M:%S} is within 30m of'
    
        for time, airline in alt_flights:
            if abs(a - str2time(time)).total_seconds() <= 1800:
                print(f"{start} {str2time(time)} {airline}", end='')
                start = ','
    
        if start == ',':
            print()
    

    Output:

    10:26:42 is within 30m of 10:49:20 Frontier, 10:34:35 Jet Blue
    08:55:43 is within 30m of 8:51:10 Southwest, 8:39:47 Delta
    07:34:11 is within 30m of 7:11:49 Spirit, 7:42:10 American