Grouping work hours for consecutive days Problem Description
The problem was initially posted here: Parse and clean up text block of store hours in Python.
Given the following multi-line string:
&quot;&quot;&quot;Hours
Monday 9:30 AM - 9:00 PM
Tuesday 9:30 AM - 9:00 PM
Wednesday 9:30 AM - 9:00 PM
Thursday 9:30 AM - 9:00 PM
Friday 9:30 AM - 11:00 PM
Saturday 9:30 AM - 11:00 PM
Sunday 11:00 AM - 6:00 PM
Holiday Hours
Thanksgiving Day 11:00 AM - 6:00 PM&quot;&quot;&quot;

Group the consecutive weekdays by the work hours, producing the following output:
&quot;&quot;&quot;Mon-Thu 9:30AM-9:00PM  
Fri-Sat 9:30AM-11:00PM
Sun &amp; Hol 11:00AM-6:00PM&quot;&quot;&quot;

Solution
My approach is based on parsing the weekday lines, splitting by the first space and then using itertools.groupby() to sort by the second item of every row, using the groupby's implementation detail - it would only group the consecutive matches together:
from itertools import groupby
from operator import itemgetter


data = &quot;&quot;&quot;Hours
Monday 9:30 AM - 9:00 PM
Tuesday 9:30 AM - 9:00 PM
Wednesday 9:30 AM - 9:00 PM
Thursday 9:30 AM - 9:00 PM
Friday 9:30 AM - 11:00 PM
Saturday 9:30 AM - 11:00 PM
Sunday 11:00 AM - 6:00 PM
Holiday Hours
Thanksgiving Day 11:00 AM - 6:00 PM&quot;&quot;&quot;

# filter relevant rows with weekdays only
rows = [row.split(&quot; &quot;, 1) for row in data.splitlines()[1:-2]]

# group consecutive days by a time range
result = []
for time_range, group in groupby(rows, key=itemgetter(1)):
    days_in_group = [item[0] for item in group]

    first_day, last_day = days_in_group[0][:3], days_in_group[-1][:3]
    range_end = &quot;-&quot; + str(last_day) if first_day != last_day else &quot;&quot;

    result.append(&quot;{begin}{end} {time_range}&quot;.format(begin=first_day,
                                                     end=range_end,
                                                     time_range=time_range))

print(&quot;\n&quot;.join(result))

Is this the most optimal solution to the problem? Is it Pythonic? What would you improve code quality-wise?
magic numbers

In

rows = [row.split(" ", 1) for row in data.splitlines()[1:-2]]


the 1 &amp; -2 magic numbers are a bit of a wart. Perhaps you'd like to create a generator that knows to suppress 'Hours' and that won't yield any further lines after 'Holiday Hours'.

Also,

first_day, last_day = days_in_group[0][:3], days_in_group[-1][:3]


has some magic numbers, but arguably they make more sense. You could make your generator responsible for day parsing, with yield day[:3], time_range.

variable renaming

In your string formatting, you choose to rename first_day to begin, and range_end to end. I suppose my advice is "don't do that". Or if there's a name you prefer for those variables, use that consistently throughout.

In

days_in_group = [item[0] for item in group]


the identifier item is a bit vague. pair would be better (or perhaps day_range if you lean toward the verbose).

global scope

You polluted the top-level namespace with rows and other identifiers. Your file cannot be reused via import. Please use the

if __name__ == '__main__':


idiom to bury these lines of code under def main(): or similar.

Overall, yes, this is sensible code, put together in pythonic fashion.