from collections import namedtuple class Sentence(namedtuple('Sentence', 'type start end words')): def __repr__(self): return 'Sentence({0.type}, {0.start}-{0.end})'.format(self) priorityOrder = ['sky', 'FG', 'precip', 'TS', 'w', 'H'] precip = Sentence('precip', 12, 24, 'Isolated showers from midday, becoming widespread in the evening') winds = Sentence('w', 12, 24, 'Gusty winds in the early afternoon') ts = Sentence('TS', 9, 24, 'Scattered thunderstorms from the late morning') hail = Sentence('H', 15, 21, 'Thunderstorms possibly severe in the afternoon with large hail') sky = Sentence('sky', 0, 0, 'Partly cloudy') sentences = set([winds, ts, hail, precip, sky]) expected = [sky, precip, ts, hail, winds] def byTime(sentence): return (sentence.start, sentence.end) # Or more briefly: byTime = lambda s: (s.start, s.end) from pprint import pprint pprint(sorted(sentences, key=byTime)) byTime(precip) < byTime(winds) def byTimeAndPriority(sentence): priority = priorityOrder.index(sentence.type) return (sentence.start, sentence.end, priority) pprint(sorted(sentences, key=byTimeAndPriority)) byTimeAndPriority(precip) < byTimeAndPriority(winds) for item in sorted(sentences, key=byTimeAndPriority): print byTimeAndPriority(item), "<=", item def generateKeyFn(items): precipStart = None precipEnd = None precipPriority = priorityOrder.index('precip') precipSentences = [item for item in items if item.type == 'precip'] if precipSentences: precipStart = min(item.start for item in precipSentences) precipEnd = max(item.end for item in precipSentences) mustFollowPrecip = ('TS', 'H') def keyFn(item): if precipStart and item.type in mustFollowPrecip: return (precipStart, precipEnd, precipPriority) priority = priorityOrder.index(item.type) return (item.start, item.end, priority) return keyFn bySpecialTime = generateKeyFn(sentences) for item in sorted(sentences, key=bySpecialTime): print bySpecialTime(item), "<=", item def generateKeyFn(items): precipStart, precipEnd = None, None precipPriority = priorityOrder.index('precip') precipSentences = [item for item in items if item.type == 'precip'] if precipSentences: precipStart = min(item.start for item in precipSentences) precipEnd = max(item.end for item in precipSentences) mustFollowPrecip = ('TS', 'H') def keyFn(item): start, end = item.start, item.end priority = priorityOrder.index(item.type) mustFollow = item.type in mustFollowPrecip if precipStart and mustFollow: start, end, priority = precipStart, precipEnd, precipPriority return (start, end, priority, mustFollow) return keyFn bySpecialTime = generateKeyFn(sentences) for item in sorted(sentences, key=bySpecialTime): print bySpecialTime(item), "<=", item def generateKeyFn(items): precipStart, precipEnd = None, None precipPriority = priorityOrder.index('precip') precipSentences = [item for item in items if item.type == 'precip'] if precipSentences: precipStart = min(item.start for item in precipSentences) precipEnd = max(item.end for item in precipSentences) typesMustFollowPrecip = ('TS', 'H') typesMustFollowTS = ('H',) def keyFn(item): start, end = item.start, item.end priority = priorityOrder.index(item.type) mustFollowTS = item.type in typesMustFollowTS mustFollowPrecip = item.type in typesMustFollowPrecip if precipStart and mustFollowPrecip: start, end, priority = precipStart, precipEnd, precipPriority return (start, end, priority, mustFollowPrecip, mustFollowTS) return keyFn bySpecialTime = generateKeyFn(sentences) for item in sorted(sentences, key=bySpecialTime): print bySpecialTime(item), "<=", item sorted(sentences, key=bySpecialTime) == expected sentencesNoPrecip = set([winds, ts, hail, sky]) sortKey = generateKeyFn(sentencesNoPrecip) for item in sorted(sentencesNoPrecip, key=sortKey): print sortKey(item), "<=", item import py def test_sortingTime(): input = [ Sentence('precip', 0, 12, 'rain in the morning'), Sentence('sky', 12, 24, 'sunny afternoon'), ] expected = ['precip', 'sky'] sortKey = generateKeyFn(input) assert [s.type for s in sorted(input, key=sortKey)] == expected def test_sortingPriority(): input = [ Sentence('sky', 0, 24, 'cloudy'), Sentence('precip', 0, 24, 'rain'), ] expected = ['precip', 'sky'] sortKey = generateKeyFn(input) assert [s.type for s in sorted(input, key=sortKey)] == expected def test_sortingTSAfterPrecip(): input = [ Sentence('TS', 0, 12, 'thunderstorms'), Sentence('precip', 12, 24, 'rain'), ] expected = ['precip', 'TS'] sortKey = generateKeyFn(input) assert [s.type for s in sorted(input, key=sortKey)] == expected def test_sortingHailAfterTSWithPrecip(): input = [ Sentence('precip', 12, 24, 'rain'), Sentence('TS', 0, 12, 'thunderstorms'), Sentence('H', 0, 6, 'hail'), ] expected = ['precip', 'TS', 'H'] sortKey = generateKeyFn(input) assert [s.type for s in sorted(input, key=sortKey)] == expected def test_sortingHailAfterTSNoPrecip(): input = [ Sentence('TS', 0, 12, 'thunderstorms'), Sentence('H', 0, 6, 'hail'), ] expected = ['TS', 'H'] sortKey = generateKeyFn(input) assert [s.type for s in sorted(input, key=sortKey)] == expected $py.test test_sort.py -v =============================================== test session starts =============================================== platform linux2 -- Python 2.7.5 -- pytest-2.3.5 -- /usr/bin/python plugins: xdist, cov collected 5 items test_sort.py:34: test_sortingTime PASSED test_sort.py:44: test_sortingPriority PASSED test_sort.py:54: test_sortingTSAfterPrecip PASSED test_sort.py:64: test_sortingHailAfterTSWithPrecip PASSED test_sort.py:75: test_sortingHailAfterTSNoPrecip FAILED ==================================================== FAILURES ===================================================== _________________________________________ test_sortingHailAfterTSNoPrecip _________________________________________ test_sort.py:82: in test_sortingHailAfterTSNoPrecip > assert [s.type for s in sorted(input, key=sortKey)] == expected E assert ['H', 'TS'] == ['TS', 'H'] E At index 0 diff: 'H' != 'TS' ======================================= 1 failed, 4 passed in 0.02 seconds =======================================