Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Returns an array of ranges representing the indices of consecutive elements in a collection matching a given predicate.
public extension Collection where Index == Int {
func consecutiveRanges(matching predicate: (Element, Element) -> Bool) -> [ClosedRange<Index>] {
return zip(self, indices).reduce(into: [ClosedRange<Index>](), { result, tuple in
let (a, b) = tuple
let previousIndex = { result.index(before: result.endIndex) }()
if let range = result.last, isMatching(self[previousIndex], a) {
result[previousIndex] = ClosedRange(uncheckedBounds: (range.lowerBound, b))
} else {
let range = ClosedRange(uncheckedBounds: (b, b))
result.append(range)
}
})
}
}
@shaps80

This comment has been minimized.

Copy link
Owner Author

@shaps80 shaps80 commented Jan 17, 2019

Example code:

struct OpeningHours {
    var weekday: Int
    var open: Int
    var close: Int
}

let hours = [
    OpeningHours(weekday: 1, open: 0700, close: 1800),
    OpeningHours(weekday: 2, open: 0700, close: 1800),
    OpeningHours(weekday: 3, open: 0700, close: 1800),
    OpeningHours(weekday: 4, open: 0700, close: 1800),
    OpeningHours(weekday: 5, open: 0700, close: 1800),
    OpeningHours(weekday: 6, open: 0900, close: 1400),
    OpeningHours(weekday: 7, open: 1100, close: 1300)
]

let ranges = hours.consecutiveRanges() { previous, next in
    return previous.open == next.open && previous.close == next.close
}

Printing the output results in:

print(ranges)

[ClosedRange(0...4), ClosedRange(5...5), ClosedRange(6...6)]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.