Skip to content
This repository has been archived by the owner on Mar 29, 2018. It is now read-only.

Sequence ops #15

Merged
merged 6 commits into from
Jun 27, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions ExSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@
2EC02FD0194ED10500619CB5 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E11AFB11943225B006BCE48 /* String.swift */; };
2EC02FD1194ED10500619CB5 /* NSArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EC241FB1946E91B0047109A /* NSArray.swift */; };
2EC02FD2194ED10500619CB5 /* ExSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E11AF891943222D006BCE48 /* ExSwift.h */; settings = {ATTRIBUTES = (Public, ); }; };
3C0AB978195C7FAF0009BDA0 /* Sequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C0AB977195C7FAF0009BDA0 /* Sequence.swift */; };
3C0AB979195C7FB20009BDA0 /* Sequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C0AB977195C7FAF0009BDA0 /* Sequence.swift */; };
3C0AB97A195C7FB30009BDA0 /* Sequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C0AB977195C7FAF0009BDA0 /* Sequence.swift */; };
3C0AB97B195C7FB30009BDA0 /* Sequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C0AB977195C7FAF0009BDA0 /* Sequence.swift */; };
3C0AB97D195C7FBC0009BDA0 /* ExSwiftSequenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C0AB97C195C7FBC0009BDA0 /* ExSwiftSequenceTests.swift */; };
3C0AB97E195C7FC20009BDA0 /* ExSwiftSequenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C0AB97C195C7FBC0009BDA0 /* ExSwiftSequenceTests.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -83,6 +89,8 @@
1ED536831943863100BDA94E /* ExSwift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExSwift.swift; sourceTree = "<group>"; };
2E8CE8EB194ECF2A008B9919 /* ExSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ExSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2EC02FBD194ED0D500619CB5 /* ExSwift-iOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ExSwift-iOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
3C0AB977195C7FAF0009BDA0 /* Sequence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sequence.swift; sourceTree = "<group>"; };
3C0AB97C195C7FBC0009BDA0 /* ExSwiftSequenceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExSwiftSequenceTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -140,6 +148,7 @@
1E11AF861943222D006BCE48 /* ExSwift */ = {
isa = PBXGroup;
children = (
3C0AB977195C7FAF0009BDA0 /* Sequence.swift */,
1ED536831943863100BDA94E /* ExSwift.swift */,
1E11AFAC1943225B006BCE48 /* Array.swift */,
1E11AFAD1943225B006BCE48 /* Dictionary.swift */,
Expand All @@ -165,6 +174,7 @@
1E11AF931943222D006BCE48 /* ExSwiftTests */ = {
isa = PBXGroup;
children = (
3C0AB97C195C7FBC0009BDA0 /* ExSwiftSequenceTests.swift */,
1E11AFA019432236006BCE48 /* ExSwiftArrayTests.swift */,
1E11AFA119432236006BCE48 /* ExSwiftDictionaryTests.swift */,
1E11AFA219432236006BCE48 /* ExSwiftFloatTests.swift */,
Expand Down Expand Up @@ -361,6 +371,7 @@
files = (
1EC241FC1946E91B0047109A /* NSArray.swift in Sources */,
1E11AFBC1943225B006BCE48 /* String.swift in Sources */,
3C0AB978195C7FAF0009BDA0 /* Sequence.swift in Sources */,
1E11AFB21943225B006BCE48 /* Array.swift in Sources */,
1ED536841943863100BDA94E /* ExSwift.swift in Sources */,
1E11AFB41943225B006BCE48 /* Dictionary.swift in Sources */,
Expand All @@ -380,8 +391,10 @@
1E11AFA619432236006BCE48 /* ExSwiftArrayTests.swift in Sources */,
1EC241FE1946E92E0047109A /* ExSwiftNSArrayTests.swift in Sources */,
2EB34F07195473AC00A8D2AF /* Dictionary.swift in Sources */,
3C0AB979195C7FB20009BDA0 /* Sequence.swift in Sources */,
1E11AFA819432236006BCE48 /* ExSwiftFloatTests.swift in Sources */,
1E11AFA719432236006BCE48 /* ExSwiftDictionaryTests.swift in Sources */,
3C0AB97D195C7FBC0009BDA0 /* ExSwiftSequenceTests.swift in Sources */,
2EB34F0C195473AC00A8D2AF /* NSArray.swift in Sources */,
2EB34F05195473AC00A8D2AF /* ExSwift.swift in Sources */,
2EB34F08195473AC00A8D2AF /* Float.swift in Sources */,
Expand All @@ -399,6 +412,7 @@
files = (
2EC02FD1194ED10500619CB5 /* NSArray.swift in Sources */,
2EC02FCD194ED10500619CB5 /* Float.swift in Sources */,
3C0AB97A195C7FB30009BDA0 /* Sequence.swift in Sources */,
2EC02FCA194ED10500619CB5 /* ExSwift.swift in Sources */,
2EC02FCE194ED10500619CB5 /* Int.swift in Sources */,
2EC02FCF194ED10500619CB5 /* Range.swift in Sources */,
Expand All @@ -418,8 +432,10 @@
1ED8FC31194EF9E1004F829A /* ExSwiftFloatTests.swift in Sources */,
1ED8FC32194EF9E1004F829A /* ExSwiftIntTests.swift in Sources */,
2EB34F0F1954744D00A8D2AF /* Dictionary.swift in Sources */,
3C0AB97B195C7FB30009BDA0 /* Sequence.swift in Sources */,
1ED8FC33194EF9E1004F829A /* ExSwiftRangeTests.swift in Sources */,
1ED8FC34194EF9E1004F829A /* ExSwiftStringTests.swift in Sources */,
3C0AB97E195C7FC20009BDA0 /* ExSwiftSequenceTests.swift in Sources */,
2EB34F141954744D00A8D2AF /* NSArray.swift in Sources */,
2EB34F0D1954744D00A8D2AF /* ExSwift.swift in Sources */,
2EB34F101954744D00A8D2AF /* Float.swift in Sources */,
Expand Down
242 changes: 242 additions & 0 deletions ExSwift/Sequence.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
//
// Sequence.swift
// ExSwift
//
// Created by Colin Eberhardt on 24/06/2014.
// Copyright (c) 2014 pNre. All rights reserved.
//

import Foundation


extension SequenceOf {

/**
* First element of the sequence
* @return First element of the sequence if present
*/
func first () -> T? {
var generator = self.generate();
return generator.next()
}

/**
* Checks if call returns true for any element of self
* @param call Function to call for each element
* @return True if call returns true for any element of self
*/
func any (call: (T) -> Bool) -> Bool {
var generator = self.generate();
while let nextItem = generator.next() {
if call(nextItem) {
return true
}
}
return false
}

/**
* Object at the specified index if exists
* @param index
* @return Object at index in sequence, nil if index is out of bounds
*/
func get (index: Int) -> T? {
var generator = self.generate();
for _ in 0..(index-1) {
generator.next()
}
return generator.next()
}

/**
* Objects in the specified range
* @param range
* @return Subsequence in range
*/
func get (range: Range<Int>) -> SequenceOf<T> {
return self.skip(range.startIndex)
.take(range.endIndex - range.startIndex)
}

/**
* Index of the first occurrence of item, if found
* @param item The item to search for
* @return Index of the matched item or nil
*/
func indexOf <U: Equatable> (item: U) -> Int? {
var index = 0;
for current in self {
if let equatable = current as? U {
if equatable == item {
return index
}
}
index++
}
return nil
}

/**
* Subsequence from n to the end of the sequence
* @return Sequence from n to the end
*/
func skip (n:Int) -> SequenceOf<T> {
var generator = self.generate();
for _ in 0..n {
generator.next()
}
return SequenceOf(generator)
}

/**
* Filters the sequence only including items that match the test
* @param include Function invoked to test elements for inclusion in the sequence
* @return Filtered sequence
*/
func filter(include: (T) -> Bool) -> SequenceOf<T> {
return SequenceOf(FilterSequence(self, include))
}

/**
* Opposite of filter
* @param exclude Function invoked to test elements for exlcusion from the sequence
* @return Filtered sequence
*/
func reject (exclude: (T -> Bool)) -> SequenceOf<T> {
return self.filter {
return !exclude($0)
}
}

/**
* Skips the elements in the sequence up until the condition returns false
* @param condition A function which returns a boolean if an element satisfies a given condition or not
* @return Elements of the sequence starting with the element which does not meet the condition
*/
func skipWhile(condition:(T) -> Bool) -> SequenceOf<T> {
var generator = self.generate();
var keepSkipping = true
while keepSkipping {
if let nextItem = generator.next() {
keepSkipping = condition(nextItem)
} else {
keepSkipping = false
}
}
return SequenceOf(generator)
}

/**
* Checks if self contains the item object
* @param item The item to search for
* @return true if self contains item
*/
func contains<T:Equatable> (item: T) -> Bool {
var generator = self.generate();
while let nextItem = generator.next() {
if nextItem as T == item {
return true;
}
}
return false
}

/**
* Returns the first n elements from self
* @return First n elements
*/
func take (n:Int) -> SequenceOf<T> {
return SequenceOf(TakeSequence(self, n))
}

/**
* Returns the elements of the sequence up until an element does not meet the condition
* @param condition A function which returns a boolean if an element satisfies a given condition or not.
* @return Elements of the sequence up until an element does not meet the condition
*/
func takeWhile (condition:(T?) -> Bool) -> SequenceOf<T> {
return SequenceOf(TakeWhileSequence(self, condition))
}
}

// a sequence adapter that implements the 'filter' functionality
struct FilterSequence<S:Sequence>: Sequence {
let sequence: S
let includeElement: (S.GeneratorType.Element) -> Bool

init(_ sequence: S, _ includeElement: (S.GeneratorType.Element) -> Bool) {
self.sequence = sequence
self.includeElement = includeElement
}

func generate() -> GeneratorOf<S.GeneratorType.Element> {
var generator = self.sequence.generate()
return GeneratorOf<S.GeneratorType.Element> {
var keepSkipping = true
var nextItem = generator.next()
while keepSkipping {
if let unwrappedItem = nextItem {
keepSkipping = !self.includeElement(unwrappedItem)
} else {
keepSkipping = false
}

if (keepSkipping) {
nextItem = generator.next()
}
}
return nextItem
}
}
}

// a sequence adapter that implements the 'take' functionality
struct TakeSequence<S:Sequence>: Sequence {
let sequence: S
let n: Int

init(_ sequence: S, _ n: Int) {
self.sequence = sequence
self.n = n
}

func generate() -> GeneratorOf<S.GeneratorType.Element> {
var count = 0
var generator = self.sequence.generate()
return GeneratorOf<S.GeneratorType.Element> {
count++
if count > self.n {
return nil
} else {
return generator.next()
}
}
}
}

// a sequence adapter that implements the 'takeWhile' functionality
struct TakeWhileSequence<S:Sequence>: Sequence {
let sequence: S
let condition: (S.GeneratorType.Element?) -> Bool

init(_ sequence:S, _ condition:(S.GeneratorType.Element?) -> Bool) {
self.sequence = sequence
self.condition = condition
}

func generate() -> GeneratorOf<S.GeneratorType.Element> {
var generator = self.sequence.generate()
var endConditionMet = false
return GeneratorOf<S.GeneratorType.Element> {
let next: S.GeneratorType.Element? = generator.next()
if !endConditionMet {
endConditionMet = !self.condition(next)
}
if endConditionMet {
return nil
} else {
return next
}
}
}
}
Loading