Search code examples
pythonlist-comprehension

How to add an extra middle step into a list comprehension?


Let's say I have a list[str] object containing timestamps in "HH:mm" format, e.g.

timestamps = ["22:58", "03:11", "12:21"]

I want to convert it to a list[int] object with the "number of minutes since midnight" values for each timestamp:

converted = [22*60+58, 3*60+11, 12*60+21]

... but I want to do it in style and use a single list comprehension to do it. A (syntactically incorrect) implementation that I naively constructed was something like:

def timestamps_to_minutes(timestamps: list[str]) -> list[int]:
    return [int(hh) * 60 + int(mm) for ts in timestamps for hh, mm = ts.split(":")]

... but this doesn't work because for hh, mm = ts.split(":") is not a valid syntax.

What would be the valid way of writing the same thing?

To clarify: I can see a formally satisfying solution in the form of:

def timestamps_to_minutes(timestamps: list[str]) -> list[int]:
    return [int(ts.split(":")[0]) * 60 + int(ts.split(":")[1]) for ts in timestamps]

... but this is highly inefficient and I don't want to split the string twice.


Solution

  • You could use an inner generator expression to do the splitting:

    [int(hh)*60 + int(mm) for hh, mm in (ts.split(':') for ts in timestamps)]
    

    Although personally, I'd rather use a helper function instead:

    def timestamp_to_minutes(timestamp: str) -> int:
        hh, mm = timestamp.split(":")
        return int(hh)*60 + int(mm)
    
    [timestamp_to_minutes(ts) for ts in timestamps]
    
    # Alternative
    list(map(timestamp_to_minutes, timestamps))