Skip to content

Instantly share code, notes, and snippets.

@fewlinesofcode
Created October 23, 2018 12:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fewlinesofcode/885e6bedf6f2a45db832a5d509a4e8b7 to your computer and use it in GitHub Desktop.
Save fewlinesofcode/885e6bedf6f2a45db832a5d509a4e8b7 to your computer and use it in GitHub Desktop.
IteratorAndSequence.swift
//: Playground - noun: a place where people can play
import UIKit
/*:
## `Date` wrapping and convenience methods
*/
let calendar = Calendar.current
extension Int {
public var days: DateComponents {
return calendarUnit(unit: .day)
}
private func calendarUnit(unit: Calendar.Component) -> DateComponents {
var dateComponents = DateComponents()
dateComponents.setValue(self, for: unit)
return dateComponents
}
}
extension Date {
private func valueForUnit(unit: Calendar.Component) -> Int {
return calendar.component(unit, from: self)
}
var weekday: Int {
return valueForUnit(unit: .weekday)
}
}
func + (date: Date, component: DateComponents) -> Date {
if let date = calendar.date(byAdding: component, to: date) {
return date
}
fatalError()
}
let date = Date()
let nextDay = date + 3.days
/*:
## Generators and sequences section
*/
class DateGenerator: IteratorProtocol {
// We are using naive approach here
// It shouldn't be used in real project
var dayOffWeekday: Int = 1 // Sunday
var N: Int = 3
private(set) var lessonsCount: Int
private(set) var startDate: Date
private var numIterations = 0
init(_ start: Date, _ numLessons: Int) {
lessonsCount = numLessons
startDate = start
}
func next() -> Date? {
guard numIterations < lessonsCount else {
return nil
}
numIterations += 1
var next = startDate + N.days
if next.weekday == dayOffWeekday {
next = next + 1.days
}
startDate = next
return next
}
}
let dg = DateGenerator(Date(), 10)
dg.N = 1
dg.dayOffWeekday = 1
while let date = dg.next() {
print(date)
}
while let date = dg.next() { // Exhausted
print(date)
}
class DateSequece: Sequence {
typealias Element = Date
typealias Iterator = DateGenerator
private var lessonsCount: Int
private var startDate: Date
init(_ start: Date, _ numLessons: Int){
lessonsCount = numLessons
startDate = start
}
func makeIterator() -> Iterator {
return DateGenerator(startDate, lessonsCount)
}
}
let sequence = Array(DateSequece(Date(), 10))
/*:
## `SequenceType` section
*/
class SimpleDateSequece: Sequence {
typealias Element = Date
typealias Iterator = AnyIterator<Element>
var lessonsCount: Int
var startDate: Date
var daysStep: Int = 1
private var numIterations = 0
init(_ start: Date, _ numLessons: Int, step: Int){
lessonsCount = numLessons
startDate = start
daysStep = step
}
func makeIterator() -> AnyIterator<Date> {
return AnyIterator({ () -> Date? in
guard self.numIterations < self.lessonsCount else {
return nil
}
self.numIterations += 1
let next = self.startDate + self.daysStep.days
self.startDate = next
return next
})
}
}
let simpleSequence = Array(SimpleDateSequece(Date(), 5, step: 4))
/*:
## Infinite sequences section
*/
class InfiniteDateGenerator: IteratorProtocol {
var startDate: Date
private var numIterations = 0
init(_ start: Date) {
startDate = start
}
func next() -> Date? {
let next = startDate + 1.days
startDate = next
return next
}
}
class InfiniteDateSequece: Sequence {
typealias Element = Date
typealias Iterator = InfiniteDateGenerator
private var startDate: Date
init(_ start: Date){
startDate = start
}
func makeIterator() -> InfiniteDateGenerator {
return InfiniteDateGenerator(startDate)
}
}
//let infiniteSequence = Array(InfiniteDateSequece(NSDate()))
let tenFirsElements = Array(InfiniteDateSequece(Date()).prefix(10))
let mondayIndex = 2
//let noMondaysSequence = Array(InfiniteDateSequece(NSDate()).filter({$0.weekday != mondayIndex}).prefix(10) ) // Infinite
let lazyNoMondaysSequence = Array(InfiniteDateSequece(Date()).lazy.filter({$0.weekday != mondayIndex}).prefix(10) ) // Finite
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment