18 |
19 |
20 |
--------------------------------------------------------------------------------
/ExSwift/ExSwift.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExSwift.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 07/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | infix operator =~ {}
12 | infix operator |~ {}
13 | infix operator .. {}
14 | infix operator <=> {}
15 |
16 | public typealias Ex = ExSwift
17 |
18 | public class ExSwift {
19 |
20 | /**
21 | Creates a wrapper that, executes function only after being called n times.
22 |
23 | :param: n No. of times the wrapper has to be called before function is invoked
24 | :param: function Function to wrap
25 | :returns: Wrapper function
26 | */
27 | public class func after (n: Int, function: (P...) -> T) -> ((P...) -> T?) {
28 |
29 | typealias Function = [P] -> T
30 |
31 | var times = n
32 |
33 | return {
34 | (params: P...) -> T? in
35 |
36 | // Workaround for the now illegal (T...) type.
37 | let adaptedFunction = unsafeBitCast(function, Function.self)
38 |
39 | if times-- <= 0 {
40 | return adaptedFunction(params)
41 | }
42 |
43 | return nil
44 | }
45 |
46 | }
47 |
48 | /**
49 | Creates a wrapper that, executes function only after being called n times
50 |
51 | :param: n No. of times the wrapper has to be called before function is invoked
52 | :param: function Function to wrap
53 | :returns: Wrapper function
54 | */
55 | public class func after (n: Int, function: Void -> T) -> (Void -> T?) {
56 | func callAfter (args: Any?...) -> T {
57 | return function()
58 | }
59 |
60 | let f = ExSwift.after(n, function: callAfter)
61 |
62 | return { f([nil]) }
63 | }
64 |
65 | /**
66 | Creates a wrapper function that invokes function once.
67 | Repeated calls to the wrapper function will return the value of the first call.
68 |
69 | :param: function Function to wrap
70 | :returns: Wrapper function
71 | */
72 | public class func once (function: (P...) -> T) -> ((P...) -> T) {
73 |
74 | typealias Function = [P] -> T
75 |
76 | var returnValue: T? = nil
77 |
78 | return { (params: P...) -> T in
79 |
80 | if returnValue != nil {
81 | return returnValue!
82 | }
83 |
84 | let adaptedFunction = unsafeBitCast(function, Function.self)
85 | returnValue = adaptedFunction(params)
86 |
87 | return returnValue!
88 |
89 | }
90 |
91 | }
92 |
93 | /**
94 | Creates a wrapper function that invokes function once.
95 | Repeated calls to the wrapper function will return the value of the first call.
96 |
97 | :param: function Function to wrap
98 | :returns: Wrapper function
99 | */
100 | public class func once (function: Void -> T) -> (Void -> T) {
101 | let f = ExSwift.once {
102 | (params: Any?...) -> T in
103 | return function()
104 | }
105 |
106 | return { f([nil]) }
107 | }
108 |
109 | /**
110 | Creates a wrapper that, when called, invokes function with any additional
111 | partial arguments prepended to those provided to the new function.
112 |
113 | :param: function Function to wrap
114 | :param: parameters Arguments to prepend
115 | :returns: Wrapper function
116 | */
117 | public class func partial (function: (P...) -> T, _ parameters: P...) -> ((P...) -> T) {
118 | typealias Function = [P] -> T
119 |
120 | return { (params: P...) -> T in
121 | let adaptedFunction = unsafeBitCast(function, Function.self)
122 | return adaptedFunction(parameters + params)
123 | }
124 | }
125 |
126 | /**
127 | Creates a wrapper (without any parameter) that, when called, invokes function
128 | automatically passing parameters as arguments.
129 |
130 | :param: function Function to wrap
131 | :param: parameters Arguments to pass to function
132 | :returns: Wrapper function
133 | */
134 | public class func bind
(function: (P...) -> T, _ parameters: P...) -> (Void -> T) {
135 | typealias Function = [P] -> T
136 |
137 | return { Void -> T in
138 | let adaptedFunction = unsafeBitCast(function, Function.self)
139 | return adaptedFunction(parameters)
140 | }
141 | }
142 |
143 | /**
144 | Creates a wrapper for function that caches the result of function's invocations.
145 |
146 | :param: function Function with one parameter to cache
147 | :returns: Wrapper function
148 | */
149 | public class func cached (function: P -> R) -> (P -> R) {
150 | var cache = [P:R]()
151 |
152 | return { (param: P) -> R in
153 | let key = param
154 |
155 | if let cachedValue = cache[key] {
156 | return cachedValue
157 | } else {
158 | let value = function(param)
159 | cache[key] = value
160 | return value
161 | }
162 | }
163 | }
164 |
165 | /**
166 | Creates a wrapper for function that caches the result of function's invocations.
167 |
168 | :param: function Function to cache
169 | :param: hash Parameters based hashing function that computes the key used to store each result in the cache
170 | :returns: Wrapper function
171 | */
172 | public class func cached (function: (P...) -> R, hash: ((P...) -> P)) -> ((P...) -> R) {
173 | typealias Function = [P] -> R
174 | typealias Hash = [P] -> P
175 |
176 | var cache = [P:R]()
177 |
178 | return { (params: P...) -> R in
179 | let adaptedFunction = unsafeBitCast(function, Function.self)
180 | let adaptedHash = unsafeBitCast(hash, Hash.self)
181 |
182 | let key = adaptedHash(params)
183 |
184 | if let cachedValue = cache[key] {
185 | return cachedValue
186 | } else {
187 | let value = adaptedFunction(params)
188 | cache[key] = value
189 | return value
190 | }
191 | }
192 | }
193 |
194 | /**
195 | Creates a wrapper for function that caches the result of function's invocations.
196 |
197 | :param: function Function to cache
198 | :returns: Wrapper function
199 | */
200 | public class func cached (function: (P...) -> R) -> ((P...) -> R) {
201 | return cached(function, hash: { (params: P...) -> P in return params[0] })
202 | }
203 |
204 | /**
205 | Utility method to return an NSRegularExpression object given a pattern.
206 |
207 | :param: pattern Regex pattern
208 | :param: ignoreCase If true the NSRegularExpression is created with the NSRegularExpressionOptions.CaseInsensitive flag
209 | :returns: NSRegularExpression object
210 | */
211 | internal class func regex (pattern: String, ignoreCase: Bool = false) -> NSRegularExpression? {
212 |
213 | var options = NSRegularExpressionOptions.DotMatchesLineSeparators.rawValue
214 |
215 | if ignoreCase {
216 | options = NSRegularExpressionOptions.CaseInsensitive.rawValue | options
217 | }
218 |
219 | var error: NSError? = nil
220 | let regex = NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions(rawValue: options), error: &error)
221 |
222 | return (error == nil) ? regex : nil
223 |
224 | }
225 |
226 | }
227 |
228 | func <=> (lhs: T, rhs: T) -> Int {
229 | if lhs < rhs {
230 | return -1
231 | } else if lhs > rhs {
232 | return 1
233 | } else {
234 | return 0
235 | }
236 | }
237 |
238 | /**
239 | * Internal methods
240 | */
241 | extension ExSwift {
242 |
243 | /**
244 | * Converts, if possible, and flattens an object from its Objective-C
245 | * representation to the Swift one.
246 | * @param object Object to convert
247 | * @returns Flattenend array of converted values
248 | */
249 | internal class func bridgeObjCObject (object: S) -> [T] {
250 | var result = [T]()
251 | let reflection = reflect(object)
252 |
253 | // object has an Objective-C type
254 | if let obj = object as? T {
255 | // object has type T
256 | result.append(obj)
257 | } else if reflection.disposition == .ObjCObject {
258 |
259 | var bridgedValue: T!?
260 |
261 | // If it is an NSArray, flattening will produce the expected result
262 | if let array = object as? NSArray {
263 | result += array.flatten()
264 | } else if let bridged = reflection.value as? T {
265 | result.append(bridged)
266 | }
267 | } else if reflection.disposition == .IndexContainer {
268 | // object is a native Swift array
269 |
270 | // recursively convert each item
271 | (0.. Float {
19 | return fabsf(self)
20 | }
21 |
22 | /**
23 | Squared root.
24 |
25 | :returns: sqrtf(self)
26 | */
27 | func sqrt () -> Float {
28 | return sqrtf(self)
29 | }
30 |
31 | /**
32 | Rounds self to the largest integer <= self.
33 |
34 | :returns: floorf(self)
35 | */
36 | func floor () -> Float {
37 | return floorf(self)
38 | }
39 |
40 | /**
41 | Rounds self to the smallest integer >= self.
42 |
43 | :returns: ceilf(self)
44 | */
45 | func ceil () -> Float {
46 | return ceilf(self)
47 | }
48 |
49 | /**
50 | Rounds self to the nearest integer.
51 |
52 | :returns: roundf(self)
53 | */
54 | func round () -> Float {
55 | return roundf(self)
56 | }
57 |
58 | /**
59 | Clamps self to a specified range.
60 |
61 | :param: min Lower bound
62 | :param: max Upper bound
63 | :returns: Clamped value
64 | */
65 | func clamp (min: Float, _ max: Float) -> Float {
66 | return Swift.max(min, Swift.min(max, self))
67 | }
68 |
69 | /**
70 | Random float between min and max (inclusive).
71 |
72 | :param: min
73 | :param: max
74 | :returns: Random number
75 | */
76 | static func random(min: Float = 0, max: Float) -> Float {
77 | let diff = max - min;
78 | let rand = Float(arc4random() % (UInt32(RAND_MAX) + 1))
79 | return ((rand / Float(RAND_MAX)) * diff) + min;
80 | }
81 |
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/ExSwift/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | co.pNre.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 0.2.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSHumanReadableCopyright
24 | Copyright © 2014 pNre. All rights reserved.
25 | NSPrincipalClass
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/ExSwift/Int.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Int.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 03/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension Int {
12 |
13 | /**
14 | Calls function self times.
15 |
16 | :param: function Function to call
17 | */
18 | func times (function: Void -> T) {
19 | (0.. Void) {
28 | (0.. (function: (Int) -> T) {
37 | (0.. Bool {
46 | return (self % 2) == 0
47 | }
48 |
49 | /**
50 | Checks if a number is odd.
51 |
52 | :returns: true if self is odd
53 | */
54 | func isOdd () -> Bool {
55 | return !isEven()
56 | }
57 |
58 | /**
59 | Iterates function, passing in integer values from self up to and including limit.
60 |
61 | :param: limit Last value to pass
62 | :param: function Function to invoke
63 | */
64 | func upTo (limit: Int, function: (Int) -> ()) {
65 | if limit < self {
66 | return
67 | }
68 |
69 | (self...limit).each(function)
70 | }
71 |
72 | /**
73 | Iterates function, passing in integer values from self down to and including limit.
74 |
75 | :param: limit Last value to pass
76 | :param: function Function to invoke
77 | */
78 | func downTo (limit: Int, function: (Int) -> ()) {
79 | if limit > self {
80 | return
81 | }
82 |
83 | Array(limit...self).reverse().each(function)
84 | }
85 |
86 | /**
87 | Clamps self to a specified range.
88 |
89 | :param: range Clamping range
90 | :returns: Clamped value
91 | */
92 | func clamp (range: Range) -> Int {
93 | return clamp(range.startIndex, range.endIndex - 1)
94 | }
95 |
96 | /**
97 | Clamps self to a specified range.
98 |
99 | :param: min Lower bound
100 | :param: max Upper bound
101 | :returns: Clamped value
102 | */
103 | func clamp (min: Int, _ max: Int) -> Int {
104 | return Swift.max(min, Swift.min(max, self))
105 | }
106 |
107 | /**
108 | Checks if self is included a specified range.
109 |
110 | :param: range Range
111 | :param: strict If true, "<" is used for comparison
112 | :returns: true if in range
113 | */
114 | func isIn (range: Range, strict: Bool = false) -> Bool {
115 | if strict {
116 | return range.startIndex < self && self < range.endIndex - 1
117 | }
118 |
119 | return range.startIndex <= self && self <= range.endIndex - 1
120 | }
121 |
122 | /**
123 | Checks if self is included in a closed interval.
124 |
125 | :param: interval Interval to check
126 | :returns: true if in the interval
127 | */
128 | func isIn (interval: ClosedInterval) -> Bool {
129 | return interval.contains(self)
130 | }
131 |
132 | /**
133 | Checks if self is included in an half open interval.
134 |
135 | :param: interval Interval to check
136 | :returns: true if in the interval
137 | */
138 | func isIn (interval: HalfOpenInterval) -> Bool {
139 | return interval.contains(self)
140 | }
141 |
142 | /**
143 | Returns an [Int] containing the digits in self.
144 |
145 | :return: Array of digits
146 | */
147 | func digits () -> [Int] {
148 | var result = [Int]()
149 |
150 | for char in String(self) {
151 | let string = String(char)
152 | if let toInt = string.toInt() {
153 | result.append(toInt)
154 | }
155 | }
156 |
157 | return result
158 | }
159 |
160 | /**
161 | Absolute value.
162 |
163 | :returns: abs(self)
164 | */
165 | func abs () -> Int {
166 | return Swift.abs(self)
167 | }
168 |
169 | /**
170 | Greatest common divisor of self and n.
171 |
172 | :param: n
173 | :returns: GCD
174 | */
175 | func gcd (n: Int) -> Int {
176 | return n == 0 ? self : n.gcd(self % n)
177 | }
178 |
179 | /**
180 | Least common multiple of self and n
181 |
182 | :param: n
183 | :returns: LCM
184 | */
185 | func lcm (n: Int) -> Int {
186 | return (self * n).abs() / gcd(n)
187 | }
188 |
189 | /**
190 | Computes the factorial of self
191 |
192 | :returns: Factorial
193 | */
194 | func factorial () -> Int {
195 | return self == 0 ? 1 : self * (self - 1).factorial()
196 | }
197 |
198 | /**
199 | Random integer between min and max (inclusive).
200 |
201 | :param: min Minimum value to return
202 | :param: max Maximum value to return
203 | :returns: Random integer
204 | */
205 | static func random(min: Int = 0, max: Int) -> Int {
206 | return Int(arc4random_uniform(UInt32((max - min) + 1))) + min
207 | }
208 |
209 | }
210 |
211 | /**
212 | NSTimeInterval conversion extensions
213 | */
214 | public extension Int {
215 |
216 | var years: NSTimeInterval {
217 | return 365 * self.days
218 | }
219 |
220 | var year: NSTimeInterval {
221 | return self.years
222 | }
223 |
224 | var days: NSTimeInterval {
225 | return 24 * self.hours
226 | }
227 |
228 | var day: NSTimeInterval {
229 | return self.days
230 | }
231 |
232 | var hours: NSTimeInterval {
233 | return 60 * self.minutes
234 | }
235 |
236 | var hour: NSTimeInterval {
237 | return self.hours
238 | }
239 |
240 | var minutes: NSTimeInterval {
241 | return 60 * self.seconds
242 | }
243 |
244 | var minute: NSTimeInterval {
245 | return self.minutes
246 | }
247 |
248 | var seconds: NSTimeInterval {
249 | return NSTimeInterval(self)
250 | }
251 |
252 | var second: NSTimeInterval {
253 | return self.seconds
254 | }
255 |
256 | }
257 |
--------------------------------------------------------------------------------
/ExSwift/NSArray.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSArray.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 10/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension NSArray {
12 |
13 | /**
14 | Converts an NSArray object to an OutType[] array containing the items in the NSArray of type OutType.
15 |
16 | :returns: Array of Swift objects
17 | */
18 | func cast () -> [OutType] {
19 | var result = [OutType]()
20 |
21 | for item : AnyObject in self {
22 | result += Ex.bridgeObjCObject(item) as [OutType]
23 | }
24 |
25 | return result
26 | }
27 |
28 | /**
29 | Flattens a multidimensional NSArray to an OutType[] array
30 | containing the items in the NSArray that can be bridged from their ObjC type to OutType.
31 |
32 | :returns: Flattened array
33 | */
34 | func flatten () -> [OutType] {
35 | var result = [OutType]()
36 | let reflection = reflect(self)
37 |
38 | for i in 0.. [AnyObject] {
51 | var result = [AnyObject]()
52 |
53 | for item in self {
54 | if let array = item as? NSArray {
55 | result += array.flattenAny()
56 | } else {
57 | result.append(item)
58 | }
59 | }
60 |
61 | return result
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/ExSwift/NSDate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | // ExSwift
4 | //
5 | // Created by Piergiuseppe Longo on 23/11/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension NSDate {
12 |
13 | // MARK: NSDate Manipulation
14 |
15 | /**
16 | Returns a new NSDate object representing the date calculated by adding the amount specified to self date
17 |
18 | :param: seconds number of seconds to add
19 | :param: minutes number of minutes to add
20 | :param: hours number of hours to add
21 | :param: days number of days to add
22 | :param: weeks number of weeks to add
23 | :param: months number of months to add
24 | :param: years number of years to add
25 | :returns: the NSDate computed
26 | */
27 | public func add(seconds: Int = 0, minutes: Int = 0, hours: Int = 0, days: Int = 0, weeks: Int = 0, months: Int = 0, years: Int = 0) -> NSDate {
28 | var calendar = NSCalendar.currentCalendar()
29 |
30 | let version = floor(NSFoundationVersionNumber)
31 |
32 | if version <= NSFoundationVersionNumber10_9_2 {
33 | var component = NSDateComponents()
34 | component.setValue(seconds, forComponent: .CalendarUnitSecond)
35 |
36 | var date : NSDate! = calendar.dateByAddingComponents(component, toDate: self, options: nil)!
37 | component = NSDateComponents()
38 | component.setValue(minutes, forComponent: .CalendarUnitMinute)
39 | date = calendar.dateByAddingComponents(component, toDate: date, options: nil)!
40 |
41 | component = NSDateComponents()
42 | component.setValue(hours, forComponent: .CalendarUnitHour)
43 | date = calendar.dateByAddingComponents(component, toDate: date, options: nil)!
44 |
45 | component = NSDateComponents()
46 | component.setValue(days, forComponent: .CalendarUnitDay)
47 | date = calendar.dateByAddingComponents(component, toDate: date, options: nil)!
48 |
49 | component = NSDateComponents()
50 | component.setValue(weeks, forComponent: .CalendarUnitWeekOfMonth)
51 | date = calendar.dateByAddingComponents(component, toDate: date, options: nil)!
52 |
53 | component = NSDateComponents()
54 | component.setValue(months, forComponent: .CalendarUnitMonth)
55 | date = calendar.dateByAddingComponents(component, toDate: date, options: nil)!
56 |
57 | component = NSDateComponents()
58 | component.setValue(years, forComponent: .CalendarUnitYear)
59 | date = calendar.dateByAddingComponents(component, toDate: date, options: nil)!
60 | return date
61 | }
62 |
63 | var date : NSDate! = calendar.dateByAddingUnit(.CalendarUnitSecond, value: seconds, toDate: self, options: nil)
64 | date = calendar.dateByAddingUnit(.CalendarUnitMinute, value: minutes, toDate: date, options: nil)
65 | date = calendar.dateByAddingUnit(.CalendarUnitDay, value: days, toDate: date, options: nil)
66 | date = calendar.dateByAddingUnit(.CalendarUnitHour, value: hours, toDate: date, options: nil)
67 | date = calendar.dateByAddingUnit(.CalendarUnitWeekOfMonth, value: weeks, toDate: date, options: nil)
68 | date = calendar.dateByAddingUnit(.CalendarUnitMonth, value: months, toDate: date, options: nil)
69 | date = calendar.dateByAddingUnit(.CalendarUnitYear, value: years, toDate: date, options: nil)
70 | return date
71 | }
72 |
73 | /**
74 | Returns a new NSDate object representing the date calculated by adding an amount of seconds to self date
75 |
76 | :param: seconds number of seconds to add
77 | :returns: the NSDate computed
78 | */
79 | public func addSeconds (seconds: Int) -> NSDate {
80 | return add(seconds: seconds)
81 | }
82 |
83 | /**
84 | Returns a new NSDate object representing the date calculated by adding an amount of minutes to self date
85 |
86 | :param: minutes number of minutes to add
87 | :returns: the NSDate computed
88 | */
89 | public func addMinutes (minutes: Int) -> NSDate {
90 | return add(minutes: minutes)
91 | }
92 |
93 | /**
94 | Returns a new NSDate object representing the date calculated by adding an amount of hours to self date
95 |
96 | :param: hours number of hours to add
97 | :returns: the NSDate computed
98 | */
99 | public func addHours(hours: Int) -> NSDate {
100 | return add(hours: hours)
101 | }
102 |
103 | /**
104 | Returns a new NSDate object representing the date calculated by adding an amount of days to self date
105 |
106 | :param: days number of days to add
107 | :returns: the NSDate computed
108 | */
109 | public func addDays(days: Int) -> NSDate {
110 | return add(days: days)
111 | }
112 |
113 | /**
114 | Returns a new NSDate object representing the date calculated by adding an amount of weeks to self date
115 |
116 | :param: weeks number of weeks to add
117 | :returns: the NSDate computed
118 | */
119 | public func addWeeks(weeks: Int) -> NSDate {
120 | return add(weeks: weeks)
121 | }
122 |
123 |
124 | /**
125 | Returns a new NSDate object representing the date calculated by adding an amount of months to self date
126 |
127 | :param: months number of months to add
128 | :returns: the NSDate computed
129 | */
130 |
131 | public func addMonths(months: Int) -> NSDate {
132 | return add(months: months)
133 | }
134 |
135 | /**
136 | Returns a new NSDate object representing the date calculated by adding an amount of years to self date
137 |
138 | :param: years number of year to add
139 | :returns: the NSDate computed
140 | */
141 | public func addYears(years: Int) -> NSDate {
142 | return add(years: years)
143 | }
144 |
145 | // MARK: Date comparison
146 |
147 | /**
148 | Checks if self is after input NSDate
149 |
150 | :param: date NSDate to compare
151 | :returns: True if self is after the input NSDate, false otherwise
152 | */
153 | public func isAfter(date: NSDate) -> Bool{
154 | return (self.compare(date) == NSComparisonResult.OrderedDescending)
155 | }
156 |
157 | /**
158 | Checks if self is before input NSDate
159 |
160 | :param: date NSDate to compare
161 | :returns: True if self is before the input NSDate, false otherwise
162 | */
163 | public func isBefore(date: NSDate) -> Bool{
164 | return (self.compare(date) == NSComparisonResult.OrderedAscending)
165 | }
166 |
167 |
168 | // MARK: Getter
169 |
170 | /**
171 | Date year
172 | */
173 | public var year : Int {
174 | get {
175 | return getComponent(.CalendarUnitYear)
176 | }
177 | }
178 |
179 | /**
180 | Date month
181 | */
182 | public var month : Int {
183 | get {
184 | return getComponent(.CalendarUnitMonth)
185 | }
186 | }
187 |
188 | /**
189 | Date weekday
190 | */
191 | public var weekday : Int {
192 | get {
193 | return getComponent(.CalendarUnitWeekday)
194 | }
195 | }
196 |
197 | /**
198 | Date weekMonth
199 | */
200 | public var weekMonth : Int {
201 | get {
202 | return getComponent(.CalendarUnitWeekOfMonth)
203 | }
204 | }
205 |
206 |
207 | /**
208 | Date days
209 | */
210 | public var days : Int {
211 | get {
212 | return getComponent(.CalendarUnitDay)
213 | }
214 | }
215 |
216 | /**
217 | Date hours
218 | */
219 | public var hours : Int {
220 |
221 | get {
222 | return getComponent(.CalendarUnitHour)
223 | }
224 | }
225 |
226 | /**
227 | Date minuts
228 | */
229 | public var minutes : Int {
230 | get {
231 | return getComponent(.CalendarUnitMinute)
232 | }
233 | }
234 |
235 | /**
236 | Date seconds
237 | */
238 | public var seconds : Int {
239 | get {
240 | return getComponent(.CalendarUnitSecond)
241 | }
242 | }
243 |
244 | /**
245 | Returns the value of the NSDate component
246 |
247 | :param: component NSCalendarUnit
248 | :returns: the value of the component
249 | */
250 |
251 | public func getComponent (component : NSCalendarUnit) -> Int {
252 | let calendar = NSCalendar.currentCalendar()
253 | let components = calendar.components(component, fromDate: self)
254 |
255 | return components.valueForComponent(component)
256 | }
257 | }
258 |
259 | extension NSDate: Strideable {
260 | public func distanceTo(other: NSDate) -> NSTimeInterval {
261 | return other - self
262 | }
263 |
264 | public func advancedBy(n: NSTimeInterval) -> Self {
265 | return self.dynamicType(timeIntervalSinceReferenceDate: self.timeIntervalSinceReferenceDate + n)
266 | }
267 | }
268 | // MARK: Arithmetic
269 |
270 | func +(date: NSDate, timeInterval: Int) -> NSDate {
271 | return date + NSTimeInterval(timeInterval)
272 | }
273 |
274 | func -(date: NSDate, timeInterval: Int) -> NSDate {
275 | return date - NSTimeInterval(timeInterval)
276 | }
277 |
278 | func +=(inout date: NSDate, timeInterval: Int) {
279 | date = date + timeInterval
280 | }
281 |
282 | func -=(inout date: NSDate, timeInterval: Int) {
283 | date = date - timeInterval
284 | }
285 |
286 | func +(date: NSDate, timeInterval: Double) -> NSDate {
287 | return date.dateByAddingTimeInterval(NSTimeInterval(timeInterval))
288 | }
289 |
290 | func -(date: NSDate, timeInterval: Double) -> NSDate {
291 | return date.dateByAddingTimeInterval(NSTimeInterval(-timeInterval))
292 | }
293 |
294 | func +=(inout date: NSDate, timeInterval: Double) {
295 | date = date + timeInterval
296 | }
297 |
298 | func -=(inout date: NSDate, timeInterval: Double) {
299 | date = date - timeInterval
300 | }
301 |
302 | func -(date: NSDate, otherDate: NSDate) -> NSTimeInterval {
303 | return date.timeIntervalSinceDate(otherDate)
304 | }
305 |
306 | extension NSDate: Equatable {
307 | }
308 |
309 | public func ==(lhs: NSDate, rhs: NSDate) -> Bool {
310 | return lhs.compare(rhs) == NSComparisonResult.OrderedSame
311 | }
312 |
313 | extension NSDate: Comparable {
314 | }
315 |
316 | public func <(lhs: NSDate, rhs: NSDate) -> Bool {
317 | return lhs.compare(rhs) == NSComparisonResult.OrderedAscending
318 | }
319 |
--------------------------------------------------------------------------------
/ExSwift/Range.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Range.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 04/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | internal extension Range {
12 |
13 | /**
14 | For each element in the range invokes function.
15 |
16 | :param: function Function to call
17 | */
18 | func times (function: () -> ()) {
19 | each { (current: T) -> () in
20 | function()
21 | }
22 | }
23 |
24 | /**
25 | For each element in the range invokes function passing the element as argument.
26 |
27 | :param: function Function to invoke
28 | */
29 | func times (function: (T) -> ()) {
30 | each (function)
31 | }
32 |
33 | /**
34 | For each element in the range invokes function passing the element as argument.
35 |
36 | :param: function Function to invoke
37 | */
38 | func each (function: (T) -> ()) {
39 | for i in self {
40 | function(i)
41 | }
42 | }
43 |
44 | /**
45 | Returns each element of the range in an array
46 |
47 | :returns: Each element of the range in an array
48 | */
49 | func toArray () -> [T] {
50 | var result: [T] = []
51 | for i in self {
52 | result.append(i)
53 | }
54 | return result
55 | }
56 |
57 | /**
58 | Range of Int with random bounds between from and to (inclusive).
59 |
60 | :param: from Lower bound
61 | :param: to Upper bound
62 | :returns: Random range
63 | */
64 | static func random (from: Int, to: Int) -> Range {
65 | let lowerBound = Int.random(min: from, max: to)
66 | let upperBound = Int.random(min: lowerBound, max: to)
67 |
68 | return lowerBound...upperBound
69 | }
70 |
71 | }
72 |
73 | /**
74 | * Operator == to compare 2 ranges first, second by start & end indexes. If first.startIndex is equal to
75 | * second.startIndex and first.endIndex is equal to second.endIndex the ranges are considered equal.
76 | */
77 | public func == (first: Range, second: Range) -> Bool {
78 | return first.startIndex == second.startIndex &&
79 | first.endIndex == second.endIndex
80 | }
81 |
--------------------------------------------------------------------------------
/ExSwift/Sequence.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Sequence.swift
3 | // ExSwift
4 | //
5 | // Created by Colin Eberhardt on 24/06/2014.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | internal extension SequenceOf {
12 |
13 | /**
14 | First element of the sequence.
15 |
16 | :returns: First element of the sequence if present
17 | */
18 | var first: T? {
19 | var generator = self.generate()
20 | return generator.next()
21 | }
22 |
23 | /**
24 | Checks if call returns true for any element of self.
25 |
26 | :param: call Function to call for each element
27 | :returns: True if call returns true for any element of self
28 | */
29 | func any (call: (T) -> Bool) -> Bool {
30 | var generator = self.generate()
31 | while let nextItem = generator.next() {
32 | if call(nextItem) {
33 | return true
34 | }
35 | }
36 | return false
37 | }
38 |
39 | /**
40 | Object at the specified index if exists.
41 |
42 | :param: index
43 | :returns: Object at index in sequence, nil if index is out of bounds
44 | */
45 | func get (index: Int) -> T? {
46 | var generator = self.generate()
47 | for _ in 0..<(index - 1) {
48 | generator.next()
49 | }
50 | return generator.next()
51 | }
52 |
53 | /**
54 | Objects in the specified range.
55 |
56 | :param: range
57 | :returns: Subsequence in range
58 | */
59 | func get (range: Range) -> SequenceOf {
60 | return self.skip(range.startIndex).take(range.endIndex - range.startIndex)
61 | }
62 |
63 | /**
64 | Index of the first occurrence of item, if found.
65 |
66 | :param: item The item to search for
67 | :returns: Index of the matched item or nil
68 | */
69 | func indexOf (item: U) -> Int? {
70 | var index = 0
71 | for current in self {
72 | if let equatable = current as? U {
73 | if equatable == item {
74 | return index
75 | }
76 | }
77 | index++
78 | }
79 | return nil
80 | }
81 |
82 | /**
83 | Subsequence from n to the end of the sequence.
84 |
85 | :param: n Number of elements to skip
86 | :returns: Sequence from n to the end
87 | */
88 | func skip (n: Int) -> SequenceOf {
89 | var generator = self.generate()
90 | for _ in 0.. Bool) -> SequenceOf {
103 | return SequenceOf(lazy(self).filter(include))
104 | }
105 |
106 | /**
107 | Opposite of filter.
108 |
109 | :param: exclude Function invoked to test elements for exlcusion from the sequence
110 | :returns: Filtered sequence
111 | */
112 | func reject (exclude: (T -> Bool)) -> SequenceOf {
113 | return self.filter {
114 | return !exclude($0)
115 | }
116 | }
117 |
118 | /**
119 | Skips the elements in the sequence up until the condition returns false.
120 |
121 | :param: condition A function which returns a boolean if an element satisfies a given condition or not
122 | :returns: Elements of the sequence starting with the element which does not meet the condition
123 | */
124 | func skipWhile(condition:(T) -> Bool) -> SequenceOf {
125 | var generator = self.generate()
126 | var checkingGenerator = self.generate()
127 |
128 | var keepSkipping = true
129 |
130 | while keepSkipping {
131 | var nextItem = checkingGenerator.next()
132 | keepSkipping = nextItem != nil ? condition(nextItem!) : false
133 |
134 | if keepSkipping {
135 | generator.next()
136 | }
137 | }
138 | return SequenceOf(generator)
139 | }
140 |
141 | /**
142 | Checks if self contains the item object.
143 |
144 | :param: item The item to search for
145 | :returns: true if self contains item
146 | */
147 | func contains (item: T) -> Bool {
148 | var generator = self.generate()
149 | while let nextItem = generator.next() {
150 | if nextItem as! T == item {
151 | return true
152 | }
153 | }
154 | return false
155 | }
156 |
157 | /**
158 | Returns the first n elements from self.
159 |
160 | :param: n Number of elements to take
161 | :returns: First n elements
162 | */
163 | func take (n: Int) -> SequenceOf {
164 | return SequenceOf(TakeSequence(self, n))
165 | }
166 |
167 | /**
168 | Returns the elements of the sequence up until an element does not meet the condition.
169 |
170 | :param: condition A function which returns a boolean if an element satisfies a given condition or not.
171 | :returns: Elements of the sequence up until an element does not meet the condition
172 | */
173 | func takeWhile (condition:(T?) -> Bool) -> SequenceOf {
174 | return SequenceOf(TakeWhileSequence(self, condition))
175 | }
176 |
177 | /**
178 | Returns each element of the sequence in an array
179 |
180 | :returns: Each element of the sequence in an array
181 | */
182 | func toArray () -> [T] {
183 | var result: [T] = []
184 | for item in self {
185 | result.append(item)
186 | }
187 | return result
188 | }
189 | }
190 |
191 | /**
192 | A sequence adapter that implements the 'take' functionality
193 | */
194 | public struct TakeSequence: SequenceType {
195 | private let sequence: S
196 | private let n: Int
197 |
198 | public init(_ sequence: S, _ n: Int) {
199 | self.sequence = sequence
200 | self.n = n
201 | }
202 |
203 | public func generate() -> GeneratorOf {
204 | var count = 0
205 | var generator = self.sequence.generate()
206 | return GeneratorOf {
207 | count++
208 | if count > self.n {
209 | return nil
210 | } else {
211 | return generator.next()
212 | }
213 | }
214 | }
215 | }
216 |
217 | /**
218 | a sequence adapter that implements the 'takeWhile' functionality
219 | */
220 | public struct TakeWhileSequence: SequenceType {
221 | private let sequence: S
222 | private let condition: (S.Generator.Element?) -> Bool
223 |
224 | public init(_ sequence:S, _ condition:(S.Generator.Element?) -> Bool) {
225 | self.sequence = sequence
226 | self.condition = condition
227 | }
228 |
229 | public func generate() -> GeneratorOf {
230 | var generator = self.sequence.generate()
231 | var endConditionMet = false
232 | return GeneratorOf {
233 | let next: S.Generator.Element? = generator.next()
234 | if !endConditionMet {
235 | endConditionMet = !self.condition(next)
236 | }
237 | if endConditionMet {
238 | return nil
239 | } else {
240 | return next
241 | }
242 | }
243 | }
244 | }
245 |
--------------------------------------------------------------------------------
/ExSwift/String.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 03/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public extension String {
12 |
13 | /**
14 | String length
15 | */
16 | var length: Int { return count(self) }
17 |
18 | /**
19 | self.capitalizedString shorthand
20 | */
21 | var capitalized: String { return capitalizedString }
22 |
23 | /**
24 | Returns the substring in the given range
25 |
26 | :param: range
27 | :returns: Substring in range
28 | */
29 | subscript (range: Range) -> String? {
30 | if range.startIndex < 0 || range.endIndex > self.length {
31 | return nil
32 | }
33 |
34 | let range = Range(start: advance(startIndex, range.startIndex), end: advance(startIndex, range.endIndex))
35 |
36 | return self[range]
37 | }
38 |
39 | /**
40 | Equivalent to at. Takes a list of indexes and returns an Array
41 | containing the elements at the given indexes in self.
42 |
43 | :param: firstIndex
44 | :param: secondIndex
45 | :param: restOfIndexes
46 | :returns: Charaters at the specified indexes (converted to String)
47 | */
48 | subscript (firstIndex: Int, secondIndex: Int, restOfIndexes: Int...) -> [String] {
49 | return at([firstIndex, secondIndex] + restOfIndexes)
50 | }
51 |
52 | /**
53 | Gets the character at the specified index as String.
54 | If index is negative it is assumed to be relative to the end of the String.
55 |
56 | :param: index Position of the character to get
57 | :returns: Character as String or nil if the index is out of bounds
58 | */
59 | subscript (index: Int) -> String? {
60 | if let char = Array(self).get(index) {
61 | return String(char)
62 | }
63 |
64 | return nil
65 | }
66 |
67 | /**
68 | Takes a list of indexes and returns an Array containing the elements at the given indexes in self.
69 |
70 | :param: indexes Positions of the elements to get
71 | :returns: Array of characters (as String)
72 | */
73 | func at (indexes: Int...) -> [String] {
74 | return indexes.map { self[$0]! }
75 | }
76 |
77 | /**
78 | Takes a list of indexes and returns an Array containing the elements at the given indexes in self.
79 |
80 | :param: indexes Positions of the elements to get
81 | :returns: Array of characters (as String)
82 | */
83 | func at (indexes: [Int]) -> [String] {
84 | return indexes.map { self[$0]! }
85 | }
86 |
87 | /**
88 | Returns an array of strings, each of which is a substring of self formed by splitting it on separator.
89 |
90 | :param: separator Character used to split the string
91 | :returns: Array of substrings
92 | */
93 | func explode (separator: Character) -> [String] {
94 | return split(self, isSeparator: { (element: Character) -> Bool in
95 | return element == separator
96 | })
97 | }
98 |
99 | /**
100 | Finds any match in self for pattern.
101 |
102 | :param: pattern Pattern to match
103 | :param: ignoreCase true for case insensitive matching
104 | :returns: Matches found (as [NSTextCheckingResult])
105 | */
106 | func matches (pattern: String, ignoreCase: Bool = false) -> [NSTextCheckingResult]? {
107 |
108 | if let regex = ExSwift.regex(pattern, ignoreCase: ignoreCase) {
109 | // Using map to prevent a possible bug in the compiler
110 | return regex.matchesInString(self, options: nil, range: NSMakeRange(0, length)).map { $0 as! NSTextCheckingResult }
111 | }
112 |
113 | return nil
114 | }
115 |
116 | /**
117 | Check is string with this pattern included in string
118 |
119 | :param: pattern Pattern to match
120 | :param: ignoreCase true for case insensitive matching
121 | :returns: true if contains match, otherwise false
122 | */
123 | func containsMatch (pattern: String, ignoreCase: Bool = false) -> Bool? {
124 | if let regex = ExSwift.regex(pattern, ignoreCase: ignoreCase) {
125 | let range = NSMakeRange(0, count(self))
126 | return regex.firstMatchInString(self, options: .allZeros, range: range) != nil
127 | }
128 |
129 | return nil
130 | }
131 |
132 | /**
133 | Replace all pattern matches with another string
134 |
135 | :param: pattern Pattern to match
136 | :param: replacementString string to replace matches
137 | :param: ignoreCase true for case insensitive matching
138 | :returns: true if contains match, otherwise false
139 | */
140 | func replaceMatches (pattern: String, withString replacementString: String, ignoreCase: Bool = false) -> String? {
141 | if let regex = ExSwift.regex(pattern, ignoreCase: ignoreCase) {
142 | let range = NSMakeRange(0, count(self))
143 | return regex.stringByReplacingMatchesInString(self, options: .allZeros, range: range, withTemplate: replacementString)
144 | }
145 |
146 | return nil
147 | }
148 |
149 | /**
150 | Inserts a substring at the given index in self.
151 |
152 | :param: index Where the new string is inserted
153 | :param: string String to insert
154 | :returns: String formed from self inserting string at index
155 | */
156 | func insert (var index: Int, _ string: String) -> String {
157 | // Edge cases, prepend and append
158 | if index > length {
159 | return self + string
160 | } else if index < 0 {
161 | return string + self
162 | }
163 |
164 | return self[0.. String {
173 | if let range = rangeOfCharacterFromSet(set.invertedSet) {
174 | return self[range.startIndex.. String {
181 | return trimmedLeft(characterSet: set)
182 | }
183 |
184 | /**
185 | Strips the specified characters from the end of self.
186 |
187 | :returns: Stripped string
188 | */
189 | func trimmedRight (characterSet set: NSCharacterSet = NSCharacterSet.whitespaceAndNewlineCharacterSet()) -> String {
190 | if let range = rangeOfCharacterFromSet(set.invertedSet, options: NSStringCompareOptions.BackwardsSearch) {
191 | return self[startIndex.. String {
198 | return trimmedRight(characterSet: set)
199 | }
200 |
201 | /**
202 | Strips whitespaces from both the beginning and the end of self.
203 |
204 | :returns: Stripped string
205 | */
206 | func trimmed () -> String {
207 | return trimmedLeft().trimmedRight()
208 | }
209 |
210 | /**
211 | Costructs a string using random chars from a given set.
212 |
213 | :param: length String length. If < 1, it's randomly selected in the range 0..16
214 | :param: charset Chars to use in the random string
215 | :returns: Random string
216 | */
217 | static func random (var length len: Int = 0, charset: String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") -> String {
218 |
219 | if len < 1 {
220 | len = Int.random(max: 16)
221 | }
222 |
223 | var result = String()
224 | let max = charset.length - 1
225 |
226 | len.times {
227 | result += charset[Int.random(min: 0, max: max)]!
228 | }
229 |
230 | return result
231 |
232 | }
233 |
234 |
235 | /**
236 | Parses a string containing a double numerical value into an optional double if the string is a well formed number.
237 |
238 | :returns: A double parsed from the string or nil if it cannot be parsed.
239 | */
240 | func toDouble() -> Double? {
241 |
242 | let scanner = NSScanner(string: self)
243 | var double: Double = 0
244 |
245 | if scanner.scanDouble(&double) {
246 | return double
247 | }
248 |
249 | return nil
250 |
251 | }
252 |
253 | /**
254 | Parses a string containing a float numerical value into an optional float if the string is a well formed number.
255 |
256 | :returns: A float parsed from the string or nil if it cannot be parsed.
257 | */
258 | func toFloat() -> Float? {
259 |
260 | let scanner = NSScanner(string: self)
261 | var float: Float = 0
262 |
263 | if scanner.scanFloat(&float) {
264 | return float
265 | }
266 |
267 | return nil
268 |
269 | }
270 |
271 | /**
272 | Parses a string containing a non-negative integer value into an optional UInt if the string is a well formed number.
273 |
274 | :returns: A UInt parsed from the string or nil if it cannot be parsed.
275 | */
276 | func toUInt() -> UInt? {
277 | if let val = self.trimmed().toInt() {
278 | if val < 0 {
279 | return nil
280 | }
281 | return UInt(val)
282 | }
283 |
284 | return nil
285 | }
286 |
287 |
288 | /**
289 | Parses a string containing a boolean value (true or false) into an optional Bool if the string is a well formed.
290 |
291 | :returns: A Bool parsed from the string or nil if it cannot be parsed as a boolean.
292 | */
293 | func toBool() -> Bool? {
294 | let text = self.trimmed().lowercaseString
295 | if text == "true" || text == "false" || text == "yes" || text == "no" {
296 | return (text as NSString).boolValue
297 | }
298 |
299 | return nil
300 | }
301 |
302 | /**
303 | Parses a string containing a date into an optional NSDate if the string is a well formed.
304 | The default format is yyyy-MM-dd, but can be overriden.
305 |
306 | :returns: A NSDate parsed from the string or nil if it cannot be parsed as a date.
307 | */
308 | func toDate(format : String? = "yyyy-MM-dd") -> NSDate? {
309 | let text = self.trimmed().lowercaseString
310 | var dateFmt = NSDateFormatter()
311 | dateFmt.timeZone = NSTimeZone.defaultTimeZone()
312 | if let fmt = format {
313 | dateFmt.dateFormat = fmt
314 | }
315 | return dateFmt.dateFromString(text)
316 | }
317 |
318 | /**
319 | Parses a string containing a date and time into an optional NSDate if the string is a well formed.
320 | The default format is yyyy-MM-dd hh-mm-ss, but can be overriden.
321 |
322 | :returns: A NSDate parsed from the string or nil if it cannot be parsed as a date.
323 | */
324 | func toDateTime(format : String? = "yyyy-MM-dd hh-mm-ss") -> NSDate? {
325 | return toDate(format: format)
326 | }
327 |
328 | }
329 |
330 | /**
331 | Repeats the string first n times
332 | */
333 | public func * (first: String, n: Int) -> String {
334 |
335 | var result = String()
336 |
337 | n.times {
338 | result += first
339 | }
340 |
341 | return result
342 |
343 | }
344 |
345 | // Pattern matching using a regular expression
346 | public func =~ (string: String, pattern: String) -> Bool {
347 |
348 | let regex = ExSwift.regex(pattern, ignoreCase: false)!
349 | let matches = regex.numberOfMatchesInString(string, options: nil, range: NSMakeRange(0, string.length))
350 |
351 | return matches > 0
352 |
353 | }
354 |
355 | // Pattern matching using a regular expression
356 | public func =~ (string: String, regex: NSRegularExpression) -> Bool {
357 |
358 | let matches = regex.numberOfMatchesInString(string, options: nil, range: NSMakeRange(0, string.length))
359 |
360 | return matches > 0
361 |
362 | }
363 |
364 | // This version also allowes to specify case sentitivity
365 | public func =~ (string: String, options: (pattern: String, ignoreCase: Bool)) -> Bool {
366 |
367 | if let matches = ExSwift.regex(options.pattern, ignoreCase: options.ignoreCase)?.numberOfMatchesInString(string, options: nil, range: NSMakeRange(0, string.length)) {
368 | return matches > 0
369 | }
370 |
371 | return false
372 |
373 | }
374 |
375 | // Match against all the alements in an array of String
376 | public func =~ (strings: [String], pattern: String) -> Bool {
377 |
378 | let regex = ExSwift.regex(pattern, ignoreCase: false)!
379 |
380 | return strings.all { $0 =~ regex }
381 |
382 | }
383 |
384 | public func =~ (strings: [String], options: (pattern: String, ignoreCase: Bool)) -> Bool {
385 |
386 | return strings.all { $0 =~ options }
387 |
388 | }
389 |
390 | // Match against any element in an array of String
391 | public func |~ (strings: [String], pattern: String) -> Bool {
392 |
393 | let regex = ExSwift.regex(pattern, ignoreCase: false)!
394 |
395 | return strings.any { $0 =~ regex }
396 |
397 | }
398 |
399 | public func |~ (strings: [String], options: (pattern: String, ignoreCase: Bool)) -> Bool {
400 |
401 | return strings.any { $0 =~ options }
402 |
403 | }
404 |
--------------------------------------------------------------------------------
/ExSwiftTests/ArrayExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ArrayExtensionsTests.swift
3 | // ExtensionsTests
4 | //
5 | // Created by pNre on 03/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 |
12 | class ArrayExtensionsSpec: QuickSpec {
13 |
14 | var intArray: [Int] = []
15 | var stringArray: [String] = []
16 |
17 | override func spec() {
18 |
19 | beforeEach { () -> () in
20 |
21 | self.intArray = [Int](1...5)
22 | self.stringArray = ["A", "B", "C", "D", "E", "F"]
23 |
24 | }
25 |
26 | /**
27 | * Array.get
28 | */
29 | describe("get") {
30 |
31 | it("in bounds") {
32 |
33 | for i in enumerate(self.intArray) {
34 | expect(self.intArray.get(i.index)) == (i.element)
35 | }
36 |
37 | }
38 |
39 | it("out of bounds") {
40 |
41 | expect(self.intArray.get(-1)).to(beNil())
42 |
43 | expect(self.intArray.get(self.intArray.count)).to(beNil())
44 |
45 | }
46 |
47 | }
48 |
49 | /**
50 | * Array.sortUsing
51 | */
52 | describe("sortUsing") {
53 |
54 | it("default item comparison") {
55 |
56 | expect(self.intArray.sortUsing { $0 }) == [1, 2, 3, 4, 5]
57 |
58 | }
59 |
60 | it("mapped item") {
61 |
62 | expect(self.intArray.sortUsing { $0 % 2 }) == [2, 4, 1, 3, 5]
63 | expect(self.intArray.sortUsing { -$0 }) == self.intArray.reverse()
64 |
65 | }
66 |
67 | }
68 |
69 | /**
70 | * Array.reject
71 | */
72 | describe("reject") {
73 |
74 | it("all/none") {
75 |
76 | expect(self.intArray.reject { _ in true }) == []
77 |
78 | expect(self.intArray.reject { _ in false }) == self.intArray
79 |
80 | }
81 |
82 | it("misc") {
83 |
84 | expect(self.intArray.reject { obj in obj > 3 }) == [1, 2, 3]
85 |
86 | expect(self.intArray.reject { obj in obj % 2 == 0 }) == [1, 3, 5]
87 |
88 | }
89 |
90 | }
91 |
92 | /**
93 | * Array.each
94 | */
95 | describe("each") {
96 |
97 | it("object param") {
98 |
99 | var data = [Int]()
100 |
101 | self.intArray.each { data.append($0) }
102 |
103 | expect(data) == self.intArray
104 |
105 | }
106 |
107 | it("index param") {
108 |
109 | var data = [Int]()
110 |
111 | self.intArray.each { index, obj in data.append(index) }
112 |
113 | expect(data) == [Int](0...4)
114 |
115 | }
116 |
117 | }
118 |
119 | /**
120 | * Array.contains
121 | */
122 | describe("contains") {
123 |
124 | it("one item") {
125 |
126 | expect(self.intArray.contains(10)).to(beFalse())
127 |
128 | expect(self.intArray.contains(4)).to(beTrue())
129 |
130 | }
131 |
132 | it("more than one item") {
133 |
134 | // Contains 1, doesn't contain 10
135 | expect(self.intArray.contains(1, 10)).to(beFalse())
136 |
137 | // Contains both 1, 2
138 | expect(self.intArray.contains(1, 2)).to(beTrue())
139 |
140 | // Doesn't contain 6, 7, 8
141 | expect(self.intArray.contains(6, 7, 8)).to(beFalse())
142 |
143 | }
144 |
145 | it("item of an invalid type") {
146 |
147 | expect(self.intArray.contains("A")).to(beFalse())
148 |
149 | }
150 |
151 | }
152 |
153 | /**
154 | * Array.indexOf
155 | */
156 | describe("indexOf") {
157 |
158 | it("with an object") {
159 |
160 | expect(self.intArray.indexOf(1)) == 0
161 | expect(self.intArray.indexOf(5)) == 4
162 |
163 | expect(self.intArray.indexOf(self.intArray[2])) == 2
164 |
165 | expect(self.intArray.indexOf(50)).to(beNil())
166 |
167 | }
168 |
169 | it("with matching block") {
170 |
171 | expect(self.intArray.indexOf { $0 % 2 == 0 }) == 1
172 |
173 | expect(self.intArray.indexOf { $0 > 10 }).to(beNil())
174 |
175 | }
176 |
177 | }
178 |
179 | /**
180 | * Array.lastIndexOf
181 | */
182 | describe("lastIndexOf") {
183 |
184 | var arrayWithDuplicates: [Int] = []
185 |
186 | beforeEach {
187 |
188 | arrayWithDuplicates = [1, 1, 2, 2, 3, 4, 1]
189 |
190 | }
191 |
192 | it("with an object") {
193 |
194 | expect(arrayWithDuplicates.lastIndexOf(1)) == 6
195 | expect(arrayWithDuplicates.lastIndexOf(4)) == 5
196 |
197 | expect(arrayWithDuplicates.lastIndexOf(arrayWithDuplicates[2])) == 3
198 |
199 | expect(arrayWithDuplicates.lastIndexOf(50)).to(beNil())
200 |
201 | }
202 |
203 | }
204 |
205 | /**
206 | * Array.max
207 | */
208 | describe("max") {
209 |
210 | it("comparable array") {
211 |
212 | expect(self.intArray.max() as Int) == 5
213 |
214 | }
215 |
216 | }
217 |
218 | /**
219 | * Array.min
220 | */
221 | describe("min") {
222 |
223 | it("comparable array") {
224 |
225 | expect(self.intArray.min() as Int) == 1
226 |
227 | }
228 |
229 | }
230 |
231 | /**
232 | * Array.at
233 | */
234 | describe("at") {
235 |
236 | it("at") {
237 |
238 | expect(self.intArray.at(0, 2)) == [1, 3]
239 |
240 | }
241 |
242 | it("subscript") {
243 |
244 | expect(self.intArray[0, 2, 1]) == [1, 3, 2]
245 |
246 | }
247 |
248 | }
249 |
250 | /**
251 | * Array.unique/uniqueBy
252 | */
253 | describe("unique/uniqueBy") {
254 |
255 | var arrayWithDuplicates: [Int] = []
256 |
257 | beforeEach {
258 |
259 | arrayWithDuplicates = [1, 1, 2, 2, 3, 4]
260 |
261 | }
262 |
263 | it("unique") {
264 |
265 | expect(arrayWithDuplicates.unique() as [Int]) == [1, 2, 3, 4]
266 |
267 | }
268 |
269 | it("uniqueBy") {
270 |
271 | expect(arrayWithDuplicates.uniqueBy { $0 }) == arrayWithDuplicates.unique()
272 |
273 | expect(arrayWithDuplicates.uniqueBy { $0 % 2 }) == [1, 2]
274 |
275 | expect(arrayWithDuplicates.uniqueBy { $0 % 3 }) == [1, 2, 3]
276 |
277 | expect(arrayWithDuplicates.uniqueBy { $0 < 3 }) == [1, 3]
278 |
279 | }
280 |
281 | }
282 |
283 | /**
284 | * Array.take/takeWhile
285 | */
286 | describe("take/takeWhile") {
287 |
288 | it("take") {
289 |
290 | expect(self.intArray.take(2)) == self.intArray[0..<2]
291 | expect(self.intArray.take(0)) == []
292 |
293 | }
294 |
295 | it("take out of bounds") {
296 |
297 | expect(self.intArray.take(6)) == self.intArray
298 | expect(self.intArray.take(-1)) == []
299 |
300 | }
301 |
302 | it("takeWhile") {
303 |
304 | expect(self.intArray.takeWhile { $0 < 3 }) == [1, 2]
305 |
306 | expect(self.intArray.takeWhile { $0 % 2 == 0 }) == []
307 |
308 | }
309 |
310 | }
311 |
312 | /**
313 | * Array.skip/skipWhile
314 | */
315 | describe("skip/skipWhile") {
316 |
317 | it("skip") {
318 |
319 | expect(self.intArray.skip(2)) == self.intArray[2.. 0 }) == []
338 |
339 | }
340 |
341 | }
342 |
343 | /**
344 | * Array.countBy
345 | */
346 | describe("countBy") {
347 |
348 | it("countBy") {
349 |
350 | let count_1 = self.intArray.countBy {
351 | return $0 % 2 == 0 ? "even" : "odd"
352 | }
353 |
354 | expect(count_1) == ["even": 2, "odd": 3]
355 |
356 | let count_2 = self.intArray.countBy { param -> Int in
357 | return 0
358 | }
359 |
360 | expect(count_2) == [0: self.intArray.count]
361 |
362 | }
363 |
364 | }
365 |
366 | /**
367 | * Array.difference
368 | */
369 | describe("difference") {
370 |
371 | it("method") {
372 |
373 | expect(self.intArray.difference([3, 4])) == [1, 2, 5]
374 |
375 | expect(self.intArray.difference([3], [4])) == [1, 2, 5]
376 |
377 | expect(self.intArray.difference([])) == self.intArray
378 |
379 | }
380 |
381 | it("operator") {
382 |
383 | expect(self.intArray - [3, 4]) == [1, 2, 5]
384 |
385 | expect(self.intArray - [3] - [4]) == [1, 2, 5]
386 |
387 | expect(self.intArray - []) == self.intArray
388 |
389 | }
390 |
391 | }
392 |
393 | /**
394 | * Array.intersection
395 | */
396 | describe("intersection") {
397 |
398 | it("method") {
399 |
400 | expect(self.intArray.intersection([])) == []
401 |
402 | expect(self.intArray.intersection([1])) == [1]
403 |
404 | expect(self.intArray.intersection([1, 2], [1, 2], [1, 2, 3])) == [1, 2]
405 |
406 | }
407 |
408 | it("operator") {
409 |
410 | expect(self.intArray & []) == []
411 |
412 | expect(self.intArray & [1]) == [1]
413 |
414 | expect(self.intArray & [1, 2] & [1, 2] & [1, 2, 3]) == [1, 2]
415 |
416 | }
417 |
418 | }
419 |
420 | /**
421 | * Array.union
422 | */
423 | describe("union") {
424 |
425 | it("method") {
426 |
427 | expect(self.intArray.union([])) == self.intArray
428 |
429 | expect(self.intArray.union([1])) == self.intArray
430 |
431 | expect(self.intArray.union([1, 5], [6], [7, 4])) == [1, 2, 3, 4, 5, 6, 7]
432 |
433 | }
434 |
435 | it("operator") {
436 |
437 | expect(self.intArray | []) == self.intArray
438 |
439 | expect(self.intArray | [1]) == self.intArray
440 |
441 | expect(self.intArray | [1, 5] | [6] | [7, 4]) == [1, 2, 3, 4, 5, 6, 7]
442 |
443 | }
444 |
445 | }
446 |
447 | /**
448 | * Array duplication
449 | */
450 | describe("duplication") {
451 |
452 | it("operator") {
453 |
454 | expect([1] * 3) == [1, 1, 1]
455 |
456 | expect(self.intArray * 0) == []
457 | expect(self.intArray * 1) == self.intArray
458 |
459 | }
460 |
461 | }
462 |
463 | /**
464 | * Array.tail
465 | */
466 | describe("tail") {
467 |
468 | it("in bounds") {
469 |
470 | expect(self.intArray.tail(0)) == []
471 |
472 | expect(self.intArray.tail(3)) == [3, 4, 5]
473 |
474 | }
475 |
476 | it("out of bounds") {
477 |
478 | expect(self.intArray.tail(10)) == self.intArray
479 |
480 | }
481 |
482 | }
483 |
484 | /**
485 | * Array.pop
486 | */
487 | describe("pop") {
488 |
489 | it("non empty array") {
490 |
491 | expect(self.intArray.pop()) == 5
492 | expect(self.intArray) == [1, 2, 3, 4]
493 |
494 | }
495 |
496 | it("empty array") {
497 |
498 | var emptyArray = [Int]()
499 |
500 | expect(emptyArray.pop()).to(beNil())
501 |
502 | }
503 |
504 | }
505 |
506 | /**
507 | * Array.push
508 | */
509 | describe("push") {
510 |
511 | it("push") {
512 |
513 | self.intArray.push(10)
514 |
515 | expect(self.intArray.last) == 10
516 |
517 | }
518 |
519 | }
520 |
521 | /**
522 | * Array.shift
523 | */
524 | describe("shift") {
525 |
526 | it("non empty array") {
527 |
528 | expect(self.intArray.shift()) == 1
529 | expect(self.intArray) == [2, 3, 4, 5]
530 |
531 | }
532 |
533 | it("empty array") {
534 |
535 | var emptyArray = [Int]()
536 |
537 | expect(emptyArray.shift()).to(beNil())
538 |
539 | }
540 |
541 | }
542 |
543 | /**
544 | * Array.unshift
545 | */
546 | describe("unshift") {
547 |
548 | it("unshift") {
549 |
550 | self.intArray.unshift(10)
551 |
552 | expect(self.intArray) == [10, 1, 2, 3, 4, 5]
553 |
554 | }
555 |
556 | }
557 |
558 | /**
559 | * Array.remove
560 | */
561 | describe("remove") {
562 |
563 | it("method") {
564 |
565 | self.intArray.remove(1)
566 |
567 | expect(self.intArray) == [2, 3, 4, 5]
568 |
569 | self.intArray.remove(6)
570 |
571 | expect(self.intArray) == [2, 3, 4, 5]
572 |
573 | }
574 |
575 | it("operator") {
576 |
577 | expect(self.intArray - 1) == [2, 3, 4, 5]
578 |
579 | expect(self.intArray - 6) == [1, 2, 3, 4, 5]
580 |
581 | }
582 | }
583 |
584 | /**
585 | * Array.toDictionary
586 | */
587 | describe("toDictionary") {
588 |
589 | it("map values to keys") {
590 |
591 | let dictionary = self.intArray.toDictionary {
592 |
593 | return "Number \($0)"
594 |
595 | }
596 |
597 | for i in enumerate(self.intArray) {
598 |
599 | expect(dictionary["Number \(i.element)"]) == i.element
600 |
601 | }
602 |
603 | }
604 |
605 | it("map keys and values") {
606 |
607 | let dictionary = self.intArray.toDictionary { (element) -> (Int, String)? in
608 |
609 | if (element > 2) {
610 | return nil
611 | }
612 |
613 | return (element, "Number \(element)")
614 |
615 | }
616 |
617 | expect(dictionary[1]) == "Number 1"
618 | expect(dictionary[2]) == "Number 2"
619 |
620 | expect(dictionary.keys.array - [1, 2]) == []
621 |
622 | }
623 |
624 | }
625 |
626 | /**
627 | * Array.implode
628 | */
629 | describe("implode") {
630 |
631 | it("method") {
632 |
633 | expect(self.stringArray.implode("")) == "ABCDEF"
634 | expect(self.stringArray.implode("*")) == "A*B*C*D*E*F"
635 |
636 | }
637 |
638 | it("operator") {
639 |
640 | expect(self.stringArray * "") == "ABCDEF"
641 | expect(self.stringArray * "*") == "A*B*C*D*E*F"
642 |
643 | }
644 |
645 | }
646 |
647 | /**
648 | * Array.flatten
649 | */
650 | describe("flatten") {
651 |
652 | var multidimensionalArray: NSArray = []
653 |
654 | beforeEach { () -> () in
655 |
656 | multidimensionalArray = [5, [6, [7]], 8]
657 |
658 | }
659 |
660 | it("flatten") {
661 |
662 | expect(multidimensionalArray.flatten() as [Int]) == [5, 6, 7, 8]
663 | expect((multidimensionalArray.flattenAny() as! [Int])) == [5, 6, 7, 8]
664 |
665 | }
666 |
667 | }
668 |
669 | /**
670 | * Array.minBy
671 | */
672 | it("minBy") {
673 |
674 | expect(self.intArray.minBy { $0 }) == 1
675 |
676 | expect(self.intArray.minBy { -$0 }) == 5
677 |
678 | expect(self.intArray.minBy { $0 % 4 }) == 4
679 |
680 | expect(self.intArray.minBy { $0 % 2 }) == 2
681 |
682 | }
683 |
684 | /**
685 | * Array.maxBy
686 | */
687 | it("maxBy") {
688 |
689 | expect(self.intArray.maxBy { $0 }) == 5
690 |
691 | expect(self.intArray.maxBy { -$0 }) == 1
692 |
693 | expect(self.intArray.maxBy { $0 % 4 }) == 3
694 |
695 | expect(self.intArray.maxBy { $0 % 3 }) == 2
696 |
697 | }
698 |
699 | /**
700 | * Array.zip
701 | */
702 | it("zip") {
703 |
704 | let zipped = self.stringArray.zip(self.intArray)
705 |
706 | expect(zipped[0].first as? String) == "A"
707 | expect(zipped[0].last as? Int) == 1
708 |
709 | expect(zipped[1].first as? String) == "B"
710 | expect(zipped[1].last as? Int) == 2
711 |
712 | expect(zipped.last!.first as? String) == "E"
713 | expect(zipped.last!.last as? Int) == 5
714 |
715 | }
716 |
717 | /**
718 | * Array.sample
719 | */
720 | it("sample") {
721 |
722 | // 0 objects
723 | let zero = self.intArray.sample(size: 0)
724 |
725 | expect(zero).to(beEmpty())
726 |
727 | // 1 object
728 | let one = self.intArray.sample()[0]
729 |
730 | expect(self.intArray).to(contain(one))
731 |
732 | // n > 1 objects
733 | let sampled = self.intArray.sample(size: 3)
734 |
735 | for item in sampled {
736 | expect(self.intArray).to(contain(item))
737 | }
738 |
739 | }
740 |
741 | /**
742 | * Array.groupBy
743 | */
744 | it("groupBy") {
745 |
746 | let group = self.intArray.groupBy(groupingFunction: {
747 | (value: Int) -> Bool in
748 | return value > 3
749 | })
750 |
751 | expect(group.keys.array) == [false, true]
752 |
753 | expect(group[true]) == [4, 5]
754 | expect(group[false]) == [1, 2, 3]
755 |
756 | }
757 |
758 | /**
759 | * Array.countWhere
760 | */
761 | it("countWhere") {
762 |
763 | expect(self.intArray.countWhere { value in true }) == self.intArray.count
764 | expect(self.intArray.countWhere { value in false }) == 0
765 |
766 | expect(self.intArray.countWhere { value in value % 2 == 0 }) == 2
767 |
768 | }
769 |
770 | /**
771 | * Array.takeFirst
772 | */
773 | it("takeFirst") {
774 |
775 | expect(self.intArray.takeFirst { value in true }) == 1
776 | expect(self.intArray.takeFirst { value in false }).to(beNil())
777 |
778 | expect(self.intArray.takeFirst { $0 % 2 == 0 }) == 2
779 | expect(self.intArray.takeFirst { $0 > 10 }).to(beNil())
780 |
781 | }
782 |
783 | /**
784 | * Array.fill
785 | */
786 | it("fill") {
787 |
788 | self.intArray.fill(0)
789 |
790 | for object in self.intArray {
791 | expect(object) == 0
792 | }
793 |
794 | var emptyArray: [String] = []
795 | emptyArray.fill("x")
796 |
797 | expect(emptyArray) == []
798 |
799 | }
800 |
801 | /**
802 | * Array.insert
803 | */
804 | it("insert") {
805 |
806 | self.intArray.insert([6, 7, 8], atIndex: 1)
807 |
808 | expect(self.intArray) == [1, 6, 7, 8, 2, 3, 4, 5]
809 |
810 | self.intArray.insert([9], atIndex: 10)
811 |
812 | expect(self.intArray) == [1, 6, 7, 8, 2, 3, 4, 5, 9]
813 |
814 | self.intArray.insert([0], atIndex: -2)
815 |
816 | expect(self.intArray) == [0, 1, 6, 7, 8, 2, 3, 4, 5, 9]
817 |
818 | }
819 |
820 | /**
821 | * Array[]
822 | */
823 | describe("subscript") {
824 |
825 | it("half open interval") {
826 |
827 | expect(self.intArray[0..<0]) == []
828 | expect(self.intArray[0..<1]) == [1]
829 | expect(self.intArray[0..<2]) == [1, 2]
830 |
831 | }
832 |
833 | it("interval") {
834 |
835 | expect(self.intArray[0...0]) == [1]
836 | expect(self.intArray[0...1]) == [1, 2]
837 | expect(self.intArray[0...2]) == [1, 2, 3]
838 |
839 | }
840 |
841 | it("list of indices") {
842 |
843 | expect(self.intArray[0, 1]) == [1, 2]
844 | expect(self.intArray[2, 4]) == [3, 5]
845 |
846 | }
847 |
848 | }
849 |
850 | /**
851 | * Array.shuffled
852 | */
853 | it("shuffled") {
854 |
855 | expect(self.intArray - self.intArray.shuffled()) == []
856 |
857 | }
858 |
859 | /**
860 | * Array.shuffle
861 | */
862 | it("shuffled") {
863 |
864 | var array = self.intArray
865 |
866 | self.intArray.shuffle()
867 |
868 | expect(self.intArray - array) == []
869 |
870 | }
871 |
872 | /**
873 | * Array.mapFilter
874 | */
875 | it("mapFilter") {
876 |
877 | let mapped = self.intArray.mapFilter { value in
878 | return value > 3 ? nil : value + 1
879 | }
880 |
881 | expect(mapped) == [2, 3, 4]
882 |
883 | }
884 |
885 | /**
886 | * Array.mapAccum
887 | */
888 | it("mapAccum") {
889 |
890 | let (accumulated, mapped) = self.intArray.mapAccum(0) { accumulator, value in
891 | return (accumulator + value, value - 1)
892 | }
893 |
894 | expect(accumulated) == self.intArray.reduce(+)
895 | expect(mapped) == self.intArray.map { $0 - 1 }
896 |
897 | }
898 |
899 | /**
900 | * Array.cycle
901 | */
902 | it("cycle") {
903 |
904 | var sum = 0
905 |
906 | self.intArray.cycle(n: 2) {
907 | sum += $0
908 | }
909 |
910 | expect(sum) == self.intArray.reduce(0, combine: +) * 2
911 |
912 | sum = 0
913 |
914 | self.intArray.cycle(n: 0) {
915 | sum += $0
916 | }
917 |
918 | expect(sum) == 0
919 |
920 | self.intArray.cycle(n: -1) {
921 | sum += $0
922 | }
923 |
924 | expect(sum) == 0
925 |
926 | }
927 |
928 | /**
929 | * Array.partition
930 | */
931 | it("partition") {
932 |
933 | expect(self.intArray.partition(2)) == [[1, 2], [3, 4]]
934 |
935 | expect(self.intArray.partition(2, step: 1)) == [[1, 2], [2, 3], [3, 4], [4, 5]]
936 |
937 | expect(self.intArray.partition(2, step: 1, pad: nil)) == [[1, 2], [2, 3], [3, 4], [4, 5], [5]]
938 | expect(self.intArray.partition(4, step: 1, pad: nil)) == [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5]]
939 |
940 | expect(self.intArray.partition(2, step: 1, pad: [6, 7, 8])) == [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]
941 | expect(self.intArray.partition(4, step: 3, pad: [6])) == [[1, 2, 3, 4], [4, 5, 6]]
942 |
943 | expect(self.intArray.partition(2, pad: [6])) == [[1, 2], [3, 4], [5, 6]]
944 |
945 | expect([1, 2, 3, 4, 5, 6].partition(2, step: 4)) == [[1, 2], [5, 6]]
946 |
947 | expect(self.intArray.partition(10)) == [[]]
948 |
949 | }
950 |
951 | /**
952 | * Array.partitionAll
953 | */
954 | it("partitionAll") {
955 |
956 | expect(self.intArray.partitionAll(2, step: 1)) == [[1, 2], [2, 3], [3, 4], [4, 5], [5]]
957 |
958 | expect(self.intArray.partitionAll(2)) == [[1, 2], [3, 4], [5]]
959 |
960 | expect(self.intArray.partitionAll(4, step: 1)) == [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5], [4, 5], [5]]
961 |
962 | }
963 |
964 | /**
965 | * Array.partitionBy
966 | */
967 | it("partitionBy") {
968 |
969 | expect(self.intArray.partitionBy { value in false }) == [self.intArray]
970 | expect(self.intArray.partitionBy { value in true }) == [self.intArray]
971 |
972 | expect([1, 2, 4, 3, 5, 6].partitionBy { $0 % 2 == 0 }) == [[1], [2, 4], [3, 5], [6]]
973 |
974 | expect([1, 7, 3, 6, 10, 12].partitionBy { $0 % 3 }) == [[1, 7], [3, 6], [10], [12]]
975 |
976 | }
977 |
978 | /**
979 | * Array.repeatedCombination
980 | */
981 | it("repeatedCombination") {
982 |
983 | var array = [1, 2, 3]
984 |
985 | expect(array.repeatedCombination(-1)) == []
986 |
987 | expect(array.repeatedCombination(0)) == [[]]
988 |
989 | expect(array.repeatedCombination(1)) == [[1], [2], [3]]
990 | expect(array.repeatedCombination(2)) == [[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]
991 | expect(array.repeatedCombination(3)) == [[1, 1, 1],[1, 1, 2], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 3, 3], [2, 2, 2], [2, 2, 3], [2, 3, 3], [3, 3, 3]]
992 | expect(array.repeatedCombination(4)) == [[1, 1, 1, 1], [1, 1, 1, 2], [1, 1, 1, 3], [1, 1, 2, 2], [1, 1, 2, 3], [1, 1, 3, 3], [1, 2, 2, 2], [1, 2, 2, 3], [1, 2, 3, 3], [1, 3, 3, 3], [2, 2, 2, 2], [2, 2, 2, 3], [2, 2, 3, 3], [2, 3, 3, 3], [3, 3, 3, 3]]
993 |
994 | }
995 |
996 | /**
997 | * Array.combination
998 | */
999 | it("combination") {
1000 |
1001 | expect(self.intArray.combination(-1)) == []
1002 |
1003 | expect(self.intArray.combination(0)) == [[]]
1004 |
1005 | expect(self.intArray.combination(1)) == [[1], [2], [3], [4], [5]]
1006 | expect(self.intArray.combination(2)) == [[1, 2], [1, 3], [1, 4], [1, 5], [2, 3], [2, 4], [2, 5], [3, 4], [3, 5], [4, 5]]
1007 | expect(self.intArray.combination(3)) == [[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], [1, 4, 5], [2, 3, 4], [2, 3, 5], [2, 4, 5], [3, 4, 5]]
1008 | expect(self.intArray.combination(4)) == [[1, 2, 3, 4], [1, 2, 3, 5], [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]]
1009 | expect(self.intArray.combination(5)) == [[1, 2, 3, 4, 5]]
1010 | expect(self.intArray.combination(6)) == []
1011 |
1012 | }
1013 |
1014 | /**
1015 | * Array.transposition
1016 | */
1017 | it("transposition") {
1018 |
1019 | var arrays: [[Int]] = [self.intArray] * self.intArray.count
1020 |
1021 | var arraysTransposition: [[Int]] = [].transposition(arrays)
1022 | arrays.eachIndex { i in
1023 | arrays[0].eachIndex { j in
1024 | expect(arrays[i][j]) == arraysTransposition[j][i]
1025 | }
1026 | }
1027 |
1028 | var jagged: [[String]] = [["a", "b", "c"], ["d", "e"], ["f", "g", "h"]]
1029 | var jaggedTransposition = [].transposition(jagged)
1030 |
1031 | expect(jaggedTransposition) == [["a", "d", "f"], ["b", "e", "g"], ["c", "h"]]
1032 |
1033 | }
1034 |
1035 | /**
1036 | * Array.permutation
1037 | */
1038 | it("permutation") {
1039 |
1040 | 1.upTo(self.intArray.count) { i in
1041 | var permutations: [[Int]] = self.intArray.permutation(i)
1042 | var factorial = 1
1043 |
1044 | for j in 1...i {
1045 | factorial *= j
1046 | }
1047 |
1048 | expect(permutations.count) == self.intArray.combination(i).count * factorial
1049 |
1050 | var mappedPermutations: [Int] = permutations.map({ (i: [Int]) -> [Int] in i.unique()}).flatten()
1051 | var flattenedPermutations: [Int] = permutations.flatten()
1052 |
1053 | expect(mappedPermutations) == flattenedPermutations
1054 | expect(permutations.flatten().all({$0 >= 1 && $0 <= 5})).to(beTrue())
1055 | expect(permutations.unique()) == permutations
1056 | }
1057 |
1058 | expect(self.intArray.permutation(-1)) == []
1059 | expect(self.intArray.permutation(0)) == [[]]
1060 | expect(self.intArray.permutation(self.intArray.count + 1)) == []
1061 |
1062 | }
1063 |
1064 | /**
1065 | * Array.repeatedPermutation
1066 | */
1067 | it("repeatedPermutation") {
1068 |
1069 | var shortArray = [1, 2]
1070 |
1071 | expect(shortArray.repeatedPermutation(0)) == []
1072 | expect(shortArray.repeatedPermutation(1)) == [[1], [2]]
1073 | expect(shortArray.repeatedPermutation(2)) == [[1, 1], [1, 2], [2, 1], [2, 2]]
1074 | expect(shortArray.repeatedPermutation(3)) == [[1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 2, 2], [2, 1, 1], [2, 1, 2], [2, 2, 1], [2, 2, 2]]
1075 |
1076 | }
1077 |
1078 | /**
1079 | * Array.bSearch
1080 | */
1081 | describe("bSearch") {
1082 |
1083 | it("findMin") {
1084 |
1085 | 1.upTo(10) { arraySize in
1086 |
1087 | var testArray: [Int] = []
1088 |
1089 | 1.upTo(arraySize) { i in
1090 | testArray += [i]
1091 | }
1092 |
1093 | for i in testArray {
1094 | expect(testArray.bSearch({ $0 >= i })) == i
1095 | }
1096 |
1097 | }
1098 |
1099 | expect(self.intArray.bSearch({ $0 >= 101 })).to(beNil())
1100 |
1101 | expect(self.intArray.bSearch({ $0 >= 0 })) == 1
1102 |
1103 | expect([].bSearch({ true })).to(beNil())
1104 |
1105 | }
1106 |
1107 | it("findAny") {
1108 |
1109 | 1.upTo(10) { arraySize in
1110 |
1111 | var testArray: [Int] = []
1112 |
1113 | 1.upTo(arraySize) { i in
1114 | testArray += [i]
1115 | }
1116 |
1117 | for i in testArray {
1118 | expect(testArray.bSearch({ $0 - i })) == i
1119 | }
1120 |
1121 | }
1122 |
1123 | expect(self.intArray.bSearch({ $0 - (self.intArray.max() + 1) })).to(beNil())
1124 | expect(self.intArray.bSearch({ $0 - (self.intArray.min() - 1) })).to(beNil())
1125 |
1126 | expect([Int]().bSearch({ $0 })).to(beNil())
1127 |
1128 | }
1129 |
1130 | }
1131 |
1132 | }
1133 |
1134 | }
1135 |
--------------------------------------------------------------------------------
/ExSwiftTests/CharacterExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CharacterExtensions.swift
3 | // ExSwift
4 | //
5 | // Created by Cenny Davidsson on 2014-12-09.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 |
12 | class CharacterExtensionsSpec: QuickSpec {
13 |
14 | override func spec() {
15 |
16 | it("toInt") {
17 |
18 | expect(Character("7").toInt()) == 7
19 |
20 | expect(Character("a").toInt()).to(beNil())
21 |
22 | }
23 |
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/ExSwiftTests/DictionaryExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DictionaryExtensionsTests.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 04/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 |
12 | class DictionaryExtensionsSpec: QuickSpec {
13 |
14 | var dictionary: [String: Int] = [String: Int]()
15 |
16 | override func spec() {
17 |
18 | beforeEach { () -> () in
19 |
20 | self.dictionary = [
21 | "A": 1,
22 | "B": 2,
23 | "C": 3
24 | ]
25 |
26 | }
27 |
28 | /**
29 | * Dictionary.has
30 | */
31 | it("has") {
32 |
33 | expect(self.dictionary.has("A")).to(beTrue())
34 | expect(self.dictionary.has("Z")).to(beFalse())
35 |
36 | }
37 |
38 | /**
39 | * Dictionary.mapValues
40 | */
41 | it("mapValues") {
42 |
43 | let mapped = self.dictionary.mapValues({ key, value -> Int in
44 | return value + 1
45 | })
46 |
47 | expect(mapped) == ["A": 2, "B": 3, "C": 4]
48 |
49 | }
50 |
51 | /**
52 | * Dictionary.map
53 | */
54 | it("map") {
55 |
56 | let mapped = self.dictionary.map({ key, value -> (String, Int) in return (key + "A", value + 1) })
57 |
58 | expect(mapped) == ["AA": 2, "BA": 3, "CA": 4]
59 |
60 | }
61 |
62 | /**
63 | * Dictionary.mapFilterValues
64 | */
65 | it("mapFilterValues") {
66 |
67 | let result = self.dictionary.mapFilterValues { (key, value) -> Int? in
68 | if key == "B" {
69 | return nil
70 | }
71 |
72 | return value + 1
73 | }
74 |
75 | expect(result) == ["A": 2, "C": 4]
76 |
77 | expect(self.dictionary.mapFilterValues { (key, value) -> Int? in nil }) == [String: Int]()
78 | expect(self.dictionary.mapFilterValues { (key, value) -> Int? in value }) == self.dictionary
79 |
80 | }
81 |
82 | /**
83 | * Dictionary.mapFilter
84 | */
85 | it("mapFilter") {
86 |
87 | let mapped = self.dictionary.mapFilter({ key, value -> (String, String)? in
88 | if key == "C" {
89 | return ("D", key)
90 | }
91 |
92 | return nil
93 | })
94 |
95 | expect(mapped) == ["D": "C"]
96 |
97 | expect(self.dictionary.mapFilter { (key, value) -> (String, String)? in nil }) == [String: String]()
98 | expect(self.dictionary.mapFilter { (key, value) -> (String, Int)? in (key, value) }) == self.dictionary
99 |
100 | }
101 |
102 | /**
103 | * Dictionary.filter
104 | */
105 | it("filter") {
106 |
107 | expect(self.dictionary.filter { key, _ in return key != "A" }) == ["B": 2, "C": 3]
108 |
109 | expect(self.dictionary.filter { key, _ in return false }) == [String: Int]()
110 | expect(self.dictionary.filter { key, _ in return true }) == self.dictionary
111 |
112 | }
113 |
114 | /**
115 | * Dictionary.countWhere
116 | */
117 | it("countWhere") {
118 |
119 | expect(self.dictionary.countWhere { key, _ in return key != "A" }) == 2
120 |
121 | expect(self.dictionary.countWhere { key, _ in return false }) == 0
122 | expect(self.dictionary.countWhere { key, _ in return true }) == 3
123 |
124 | }
125 |
126 | /**
127 | * Dictionary.any
128 | */
129 | it("any") {
130 |
131 | expect(self.dictionary.any { _, value -> Bool in return value % 2 == 0 }).to(beTrue())
132 |
133 | expect(self.dictionary.any { _, value -> Bool in return value >= 0 }).to(beTrue())
134 |
135 | expect(self.dictionary.any { _, value -> Bool in return value < 0 }).to(beFalse())
136 |
137 | }
138 |
139 | /**
140 | * Dictionary.all
141 | */
142 | it("all") {
143 |
144 | expect(self.dictionary.all { _, value -> Bool in return value % 2 == 0 }).to(beFalse())
145 |
146 | expect(self.dictionary.all { _, value -> Bool in return value >= 0 }).to(beTrue())
147 |
148 | expect(self.dictionary.all { _, value -> Bool in return value < 0 }).to(beFalse())
149 |
150 | }
151 |
152 | /**
153 | * Dictionary.shift
154 | */
155 | it("shift") {
156 |
157 | let unshifted = self.dictionary
158 | let (key, value) = self.dictionary.shift()!
159 |
160 | expect(unshifted.keys.array).to(contain(key))
161 | expect(self.dictionary.keys.array).toNot(contain(key))
162 |
163 | expect(unshifted[key]) == value
164 | expect(self.dictionary[key]).to(beNil())
165 |
166 | expect(unshifted.values.array).to(contain(value))
167 | expect(self.dictionary.values.array).toNot(contain(value))
168 |
169 | }
170 |
171 | /**
172 | * Dictionary.pick
173 | */
174 | it("pick") {
175 |
176 | let pick1 = self.dictionary.pick(["A", "C"])
177 |
178 | expect(pick1) == ["A": 1, "C": 3]
179 |
180 | let pick2 = self.dictionary.pick("A", "C")
181 |
182 | expect(pick2) == pick1
183 |
184 | expect(self.dictionary.pick(["K"])) == [:]
185 | expect(self.dictionary.pick([])) == [:]
186 | expect(self.dictionary.pick()) == [:]
187 |
188 | }
189 |
190 | /**
191 | * Dictionary.groupBy
192 | */
193 | it("groupBy") {
194 |
195 | let grouped = self.dictionary.groupBy { _, value -> Bool in
196 | return (value % 2 == 0)
197 | }
198 |
199 | expect(grouped.keys.array - [false, true]).to(beEmpty())
200 | expect(grouped[true]) == [2]
201 |
202 | expect(grouped[false]!.count) == 2
203 | expect(grouped[false]! - [1, 3]).to(beEmpty())
204 |
205 | }
206 |
207 | /**
208 | * Dictionary.countBy
209 | */
210 | it("countBy") {
211 |
212 | let grouped = self.dictionary.countBy { _, value -> Bool in
213 | return (value % 2 == 0)
214 | }
215 |
216 | expect(grouped.keys.array - [false, true]).to(beEmpty())
217 | expect(grouped[true]) == 1
218 | expect(grouped[false]) == 2
219 |
220 | }
221 |
222 | /**
223 | * Dictionary.reduce
224 | */
225 | it("reduce") {
226 |
227 | let reduced1 = self.dictionary.reduce([Int: String](), combine: {
228 | (var initial: [Int: String], couple: (String, Int)) in
229 | initial.updateValue(couple.0, forKey: couple.1)
230 | return initial
231 | })
232 |
233 | expect(reduced1) == [2: "B", 3: "C", 1: "A"]
234 |
235 | let reduced2 = self.dictionary.reduce(0, combine: { (initial: Int, couple: (String, Int)) in
236 | return initial + couple.1
237 | })
238 |
239 | expect(reduced2) == self.dictionary.values.array.reduce(+)
240 |
241 | }
242 |
243 | /**
244 | * Dictionary.difference
245 | */
246 | describe("difference") {
247 |
248 | let dictionary1 = [ "A": 1, "B": 2, "C": 3 ]
249 | let dictionary2 = [ "A": 1 ]
250 | let dictionary3 = [ "B": 2, "C": 3 ]
251 |
252 | it("operator") {
253 |
254 | expect(self.dictionary - dictionary1) == [:]
255 | expect(self.dictionary - dictionary2) == [ "B": 2, "C": 3 ]
256 | expect(self.dictionary - dictionary3) == [ "A": 1 ]
257 |
258 | expect(dictionary2 - dictionary3) != (dictionary3 - dictionary2)
259 |
260 | expect(dictionary2 - dictionary3) == dictionary2
261 | expect(dictionary2 - [:]) == dictionary2
262 |
263 | }
264 |
265 | it("method") {
266 |
267 | expect(self.dictionary.difference(dictionary1)) == [:]
268 | expect(self.dictionary.difference(dictionary2)) == [ "B": 2, "C": 3 ]
269 | expect(self.dictionary.difference(dictionary3)) == [ "A": 1 ]
270 |
271 | expect(dictionary2.difference(dictionary3)) != dictionary3.difference(dictionary2)
272 |
273 | expect(dictionary2.difference(dictionary3)) == dictionary2
274 | expect(dictionary2.difference([:])) == dictionary2
275 |
276 | }
277 |
278 | }
279 |
280 | /**
281 | * Dictionary.union
282 | */
283 | describe("union") {
284 |
285 | let dictionary1 = [ "A": 1, "B": 2, "C": 3 ]
286 | let dictionary2 = [ "A": 1 ]
287 | let dictionary3 = [ "B": 2, "C": 3 ]
288 |
289 | it("operator") {
290 |
291 | expect(self.dictionary | dictionary1) == self.dictionary
292 | expect(self.dictionary | dictionary2) == self.dictionary
293 | expect(self.dictionary | dictionary3) == self.dictionary
294 |
295 | expect(dictionary2 | dictionary3) == (dictionary3 | dictionary2)
296 | expect(dictionary2 | dictionary3) == self.dictionary
297 |
298 | expect(dictionary1 | [:]) == dictionary1
299 |
300 | }
301 |
302 | it("method") {
303 |
304 | expect(self.dictionary.union(dictionary1)) == self.dictionary
305 | expect(self.dictionary.union(dictionary2)) == self.dictionary
306 | expect(self.dictionary.union(dictionary3)) == self.dictionary
307 |
308 | expect(dictionary2.union(dictionary3)) == dictionary3.union(dictionary2)
309 | expect(dictionary2.union(dictionary3)) == self.dictionary
310 |
311 | expect(dictionary1.union([:])) == dictionary1
312 |
313 | }
314 |
315 | }
316 |
317 | /**
318 | * Dictionary.intersection
319 | */
320 | describe("intersection") {
321 |
322 | let dictionary1 = [ "A": 1, "B": 2, "C": 3 ]
323 | let dictionary2 = [ "A": 1 ]
324 | let dictionary3 = [ "B": 2, "C": 3 ]
325 |
326 | it("operator") {
327 |
328 | expect(self.dictionary & dictionary1) == self.dictionary
329 | expect(self.dictionary & dictionary2) == dictionary2
330 | expect(self.dictionary & dictionary3) == dictionary3
331 |
332 | expect(dictionary2 & dictionary3) == (dictionary3 & dictionary2)
333 | expect(dictionary2 & dictionary3) == [String: Int]()
334 |
335 | expect(dictionary1 & [:]) == [:]
336 |
337 | }
338 |
339 | it("method") {
340 |
341 | expect(self.dictionary.intersection(dictionary1)) == self.dictionary
342 | expect(self.dictionary.intersection(dictionary2)) == dictionary2
343 | expect(self.dictionary.intersection(dictionary3)) == dictionary3
344 |
345 | expect(dictionary2.intersection(dictionary3)) == dictionary3.intersection(dictionary2)
346 | expect(dictionary2.intersection(dictionary3)) == [String: Int]()
347 |
348 | expect(dictionary1.intersection([:])) == [String: Int]()
349 |
350 | }
351 |
352 | }
353 |
354 | /**
355 | * Dictionary.toArray
356 | */
357 | it("toArray") {
358 |
359 | expect(self.dictionary.toArray({ (key, value) -> String in key })) == self.dictionary.keys.array
360 | expect(self.dictionary.toArray({ (key, value) -> Int in value })) == self.dictionary.values.array
361 |
362 | expect(self.dictionary.toArray({ (key, value) -> Bool in false })) == [false, false, false]
363 |
364 | }
365 |
366 | }
367 |
368 | }
369 |
--------------------------------------------------------------------------------
/ExSwiftTests/DoubleExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DoubleExtensionsTests.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 10/07/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 |
12 | class DoubleExtensionsSpec: QuickSpec {
13 |
14 | override func spec() {
15 |
16 | /**
17 | * Double.abs
18 | */
19 | it("abs") {
20 |
21 | expect(Double(0).abs()) == Double(0)
22 |
23 | expect(Double(-1).abs()).to(beCloseTo(1, within: 0.001))
24 | expect(Double(1).abs()).to(beCloseTo(1, within: 0.001))
25 |
26 | expect(Double(-111.2).abs()).to(beCloseTo(111.2, within: 0.001))
27 | expect(Double(111.2).abs()).to(beCloseTo(111.2, within: 0.001))
28 |
29 | }
30 |
31 | /**
32 | * Double.sqrt
33 | */
34 | it("sqrt") {
35 |
36 | expect(Double(0).sqrt()) == Double(0)
37 |
38 | expect(Double(4).sqrt()).to(beCloseTo(2, within: 0.001))
39 | expect(Double(111.2).sqrt()).to(beCloseTo(sqrt(111.2), within: 0.001))
40 |
41 | expect(isnan(Double(-10).sqrt())).to(beTrue())
42 |
43 | }
44 |
45 | /**
46 | * Double.floor
47 | */
48 | it("floor") {
49 |
50 | expect(Double(0).floor()) == Double(0)
51 |
52 | expect(Double(4.99999999).floor()).to(beCloseTo(4, within: 0.001))
53 | expect(Double(4.001).floor()).to(beCloseTo(4, within: 0.001))
54 | expect(Double(4.5).floor()).to(beCloseTo(4, within: 0.001))
55 |
56 | expect(Double(-4.99999999).floor()).to(beCloseTo(-5, within: 0.001))
57 | expect(Double(-4.001).floor()).to(beCloseTo(-5, within: 0.001))
58 | expect(Double(-4.5).floor()).to(beCloseTo(-5, within: 0.001))
59 |
60 | }
61 |
62 | /**
63 | * Double.ceil
64 | */
65 | it("ceil") {
66 |
67 | expect(Double(0).ceil()) == Double(0)
68 |
69 | expect(Double(4.99999999).ceil()).to(beCloseTo(5, within: 0.001))
70 | expect(Double(4.001).ceil()).to(beCloseTo(5, within: 0.001))
71 | expect(Double(4.5).ceil()).to(beCloseTo(5, within: 0.001))
72 |
73 | expect(Double(-4.99999999).ceil()).to(beCloseTo(-4, within: 0.001))
74 | expect(Double(-4.001).ceil()).to(beCloseTo(-4, within: 0.001))
75 | expect(Double(-4.5).ceil()).to(beCloseTo(-4, within: 0.001))
76 |
77 | }
78 |
79 | /**
80 | * Double.round
81 | */
82 | it("round") {
83 |
84 | expect(Double(0).round()) == Double(0)
85 |
86 | expect(Double(4.99999999).round()).to(beCloseTo(5, within: 0.001))
87 | expect(Double(4.001).round()).to(beCloseTo(4, within: 0.001))
88 | expect(Double(4.5).round()).to(beCloseTo(5, within: 0.001))
89 |
90 | expect(Double(4.3).round()).to(beCloseTo(4, within: 0.001))
91 | expect(Double(4.7).round()).to(beCloseTo(5, within: 0.001))
92 |
93 | expect(Double(-4.99999999).round()).to(beCloseTo(-5, within: 0.001))
94 | expect(Double(-4.001).round()).to(beCloseTo(-4, within: 0.001))
95 | expect(Double(-4.5).round()).to(beCloseTo(-5, within: 0.001))
96 |
97 | }
98 |
99 | /**
100 | * Double.roundToNearest
101 | */
102 | it("roundToNearest") {
103 |
104 | expect(2.5.roundToNearest(0.3)).to(beCloseTo(2.4, within: 0.01))
105 | expect(0.roundToNearest(0.3)).to(beCloseTo(0.0, within: 0.01))
106 | expect(4.0.roundToNearest(2)).to(beCloseTo(4.0, within: 0.01))
107 | expect(10.0.roundToNearest(3)).to(beCloseTo(9.0, within: 0.01))
108 | expect(-2.0.roundToNearest(3)).to(beCloseTo(-3.0, within: 0.01))
109 |
110 | }
111 |
112 | /**
113 | * Double.clamp
114 | */
115 | it("clamp") {
116 |
117 | expect(Double(0.25).clamp(0, 0.5)).to(beCloseTo(0.25, within: 0.01))
118 | expect(Double(2).clamp(0, 0.5)).to(beCloseTo(0.5, within: 0.01))
119 | expect(Double(-2).clamp(0, 0.5)).to(beCloseTo(0, within: 0.01))
120 |
121 | }
122 |
123 | }
124 |
125 | }
126 |
--------------------------------------------------------------------------------
/ExSwiftTests/ExSwiftBoolTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExSwiftBoolTests.swift
3 | // ExSwift
4 | //
5 | // Created by Hernandez Alvarez, David on 2/10/15.
6 | // Copyright (c) 2015 pNre. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class ExSwiftBoolTests: XCTestCase {
12 |
13 | func testToogleTrue() {
14 | var bool: Bool = false
15 | XCTAssertTrue(bool.toggle(), "Bool did not toogle to true")
16 | }
17 |
18 | func testToogleFalse() {
19 | var bool: Bool = true
20 | XCTAssertFalse(bool.toggle(), "Bool did not toogle to false")
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/ExSwiftTests/ExSwiftTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExSwiftTests.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 07/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 |
12 | class ExSwiftSpec: QuickSpec {
13 |
14 | override func spec() {
15 |
16 | it("after") {
17 |
18 | let f = ExSwift.after(2, function: { () -> Bool in return true })
19 |
20 | expect(f()).to(beNil())
21 | expect(f()).to(beNil())
22 |
23 | expect(f()).to(beTrue())
24 |
25 | var called = false
26 | let g = ExSwift.after(2, function: { called = true })
27 |
28 | g()
29 |
30 | expect(called).to(beFalse())
31 |
32 | g()
33 |
34 | expect(called).to(beFalse())
35 |
36 | g()
37 |
38 | expect(called).to(beTrue())
39 |
40 | }
41 |
42 | it("once") {
43 |
44 | var seq = [1, 2, 3, 4].generate()
45 |
46 | let g = Ex.once { Void -> Int in
47 | return seq.next()!
48 | }
49 |
50 | expect(g()) == 1
51 | expect(g()) == 1
52 |
53 | }
54 |
55 | it("partial") {
56 |
57 | let add = { (params: Int...) -> Int in
58 | return params.reduce(0, combine: +)
59 | }
60 |
61 | let add5 = ExSwift.partial(add, 5)
62 |
63 | expect(add5(10)) == 15
64 | expect(add5(1, 2)) == 8
65 |
66 | }
67 |
68 | it("bind") {
69 |
70 | let concat = { (params: String...) -> String in
71 | return params.implode(" ")!
72 | }
73 |
74 | let helloWorld = ExSwift.bind(concat, "Hello", "World")
75 |
76 | expect(helloWorld()) == "Hello World"
77 |
78 | }
79 |
80 | it("cached") {
81 |
82 | var calls = 0
83 |
84 | // Slow Fibonacci
85 | var fib: ((Int...) -> Int)!
86 | fib = { (params: Int...) -> Int in
87 | let n = params[0]
88 |
89 | calls++
90 |
91 | if n <= 1 {
92 | return n
93 | }
94 | return fib(n - 1) + fib(n - 2)
95 | }
96 |
97 | let fibonacci = Ex.cached(fib)
98 |
99 | // This one is computed (fib is called 465 times)
100 | fibonacci(12)
101 | expect(calls) == 465
102 |
103 | // The results is taken from the cache (fib is not called again)
104 | fibonacci(12)
105 | expect(calls) == 465
106 |
107 | }
108 |
109 | describe("operators") {
110 |
111 | it("spaceship") {
112 |
113 | expect(4 <=> 5) == -1
114 | expect(5 <=> 4) == 1
115 | expect(4 <=> 4) == 0
116 |
117 | }
118 |
119 | }
120 |
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/ExSwiftTests/FloatExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FloatExtensionsTests.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 04/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 |
12 | class FloatExtensionsSpec: QuickSpec {
13 |
14 | override func spec() {
15 |
16 | /**
17 | * Float.abs
18 | */
19 | it("abs") {
20 |
21 | expect(Float(0).abs()) == Float(0)
22 |
23 | expect(Float(-1).abs()).to(beCloseTo(1, within: 0.001))
24 | expect(Float(1).abs()).to(beCloseTo(1, within: 0.001))
25 |
26 | expect(Float(-111.2).abs()).to(beCloseTo(111.2, within: 0.001))
27 | expect(Float(111.2).abs()).to(beCloseTo(111.2, within: 0.001))
28 |
29 | }
30 |
31 | /**
32 | * Float.sqrt
33 | */
34 | it("sqrt") {
35 |
36 | expect(Float(0).sqrt()) == Float(0)
37 |
38 | expect(Float(4).sqrt()).to(beCloseTo(2, within: 0.001))
39 | expect(Float(111.2).sqrt()).to(beCloseTo(sqrt(111.2), within: 0.001))
40 |
41 | expect(isnan(Float(-10).sqrt())).to(beTrue())
42 |
43 | }
44 |
45 | /**
46 | * Float.floor
47 | */
48 | it("floor") {
49 |
50 | expect(Float(0).floor()) == Float(0)
51 |
52 | expect(Float(4.99999).floor()).to(beCloseTo(4, within: 0.001))
53 | expect(Float(4.001).floor()).to(beCloseTo(4, within: 0.001))
54 | expect(Float(4.5).floor()).to(beCloseTo(4, within: 0.001))
55 |
56 | expect(Float(-4.99999).floor()).to(beCloseTo(-5, within: 0.001))
57 | expect(Float(-4.001).floor()).to(beCloseTo(-5, within: 0.001))
58 | expect(Float(-4.5).floor()).to(beCloseTo(-5, within: 0.001))
59 |
60 | }
61 |
62 | /**
63 | * Float.ceil
64 | */
65 | it("ceil") {
66 |
67 | expect(Float(0).ceil()) == Float(0)
68 |
69 | expect(Float(4.99999).ceil()).to(beCloseTo(5, within: 0.001))
70 | expect(Float(4.001).ceil()).to(beCloseTo(5, within: 0.001))
71 | expect(Float(4.5).ceil()).to(beCloseTo(5, within: 0.001))
72 |
73 | expect(Float(-4.99999).ceil()).to(beCloseTo(-4, within: 0.001))
74 | expect(Float(-4.001).ceil()).to(beCloseTo(-4, within: 0.001))
75 | expect(Float(-4.5).ceil()).to(beCloseTo(-4, within: 0.001))
76 |
77 | }
78 |
79 | /**
80 | * Float.round
81 | */
82 | it("round") {
83 |
84 | expect(Float(0).round()) == Float(0)
85 |
86 | expect(Float(4.99999999).round()).to(beCloseTo(5, within: 0.001))
87 | expect(Float(4.001).round()).to(beCloseTo(4, within: 0.001))
88 | expect(Float(4.5).round()).to(beCloseTo(5, within: 0.001))
89 |
90 | expect(Float(4.3).round()).to(beCloseTo(4, within: 0.001))
91 | expect(Float(4.7).round()).to(beCloseTo(5, within: 0.001))
92 |
93 | expect(Float(-4.99999999).round()).to(beCloseTo(-5, within: 0.001))
94 | expect(Float(-4.001).round()).to(beCloseTo(-4, within: 0.001))
95 | expect(Float(-4.5).round()).to(beCloseTo(-5, within: 0.001))
96 |
97 | }
98 |
99 | /**
100 | * Float.roundToNearest
101 | */
102 | it("roundToNearest") {
103 |
104 | expect(2.5.roundToNearest(0.3)).to(beCloseTo(2.4, within: 0.01))
105 | expect(0.roundToNearest(0.3)).to(beCloseTo(0.0, within: 0.01))
106 | expect(4.0.roundToNearest(2)).to(beCloseTo(4.0, within: 0.01))
107 | expect(10.0.roundToNearest(3)).to(beCloseTo(9.0, within: 0.01))
108 | expect(-2.0.roundToNearest(3)).to(beCloseTo(-3.0, within: 0.01))
109 |
110 | }
111 |
112 | /**
113 | * Float.clamp
114 | */
115 | it("clamp") {
116 |
117 | expect(Float(0.25).clamp(0, 0.5)).to(beCloseTo(0.25, within: 0.01))
118 | expect(Float(2).clamp(0, 0.5)).to(beCloseTo(0.5, within: 0.01))
119 | expect(Float(-2).clamp(0, 0.5)).to(beCloseTo(0, within: 0.01))
120 |
121 | }
122 |
123 | }
124 |
125 | }
126 |
--------------------------------------------------------------------------------
/ExSwiftTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | co.pNre.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ExSwiftTests/IntExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // IntExtensionsTests.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 03/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 |
12 | class IntExtensionsSpec: QuickSpec {
13 |
14 | override func spec() {
15 |
16 | /**
17 | * Int.times
18 | */
19 | describe("times") {
20 |
21 | it("iteration") {
22 |
23 | var count = 0
24 |
25 | 5.times { count++ }
26 | expect(count).to(equal(5))
27 |
28 | 0.times { count++ }
29 | expect(count).to(equal(5))
30 |
31 | }
32 |
33 | it("index") {
34 |
35 | var indexes = [Int]()
36 | 5.times(indexes.append)
37 |
38 | expect(indexes) == [0, 1, 2, 3, 4]
39 |
40 | }
41 |
42 | }
43 |
44 | /**
45 | * Int.even
46 | */
47 | it("even") {
48 |
49 | expect((-1).isEven()).to(beFalse())
50 | expect(3.isEven()).to(beFalse())
51 |
52 | expect((-2).isEven()).to(beTrue())
53 | expect(4.isEven()).to(beTrue())
54 |
55 | }
56 |
57 | /**
58 | * Int.odd
59 | */
60 | it("odd") {
61 |
62 | expect((-1).isOdd()).to(beTrue())
63 | expect(3.isOdd()).to(beTrue())
64 |
65 | expect((-2).isOdd()).to(beFalse())
66 | expect(4.isOdd()).to(beFalse())
67 |
68 | }
69 |
70 | /**
71 | * Int.random
72 | */
73 | it("random") {
74 |
75 | var indexes = [Int]()
76 | 10.times { indexes.append(Int.random(min: 5, max: 25)) }
77 |
78 | expect(indexes).to(allPass { $0 >= 5 && $0 <= 25 })
79 |
80 | }
81 |
82 | /**
83 | * Int.upTo
84 | */
85 | it("upTo") {
86 |
87 | var result = [Int]()
88 | 5.upTo(10, function: result.append)
89 |
90 | expect(result) == [Int](5...10)
91 |
92 | }
93 |
94 | /**
95 | * Int.downTo
96 | */
97 | it("downTo") {
98 |
99 | var result = [Int]()
100 | 5.downTo(0, function: result.append)
101 |
102 | expect(result) == [5, 4, 3, 2, 1, 0]
103 |
104 | }
105 |
106 | /**
107 | * Int.clamp
108 | */
109 | it("clamp") {
110 |
111 | expect(5.clamp(0...4)) == 4
112 | expect(3.clamp(0...4)) == 3
113 | expect(1.clamp(2...4)) == 2
114 |
115 | }
116 |
117 | /**
118 | * Int.isIn
119 | */
120 | it("isIn") {
121 |
122 | expect(2.isIn(0..<3)).to(beTrue())
123 | expect(2.isIn(0..<3, strict: true)).to(beFalse())
124 |
125 | expect(0.isIn(0..<3)).to(beTrue())
126 | expect(0.isIn(0..<3, strict: true)).to(beFalse())
127 |
128 | expect(2.isIn(0...2)).to(beTrue())
129 | expect(2.isIn(0...2, strict: true)).to(beFalse())
130 |
131 | }
132 |
133 | /**
134 | * Int.explode
135 | */
136 | it("explode") {
137 |
138 | expect(0.digits()) == [0]
139 |
140 | expect(1234.digits()) == [1, 2, 3, 4]
141 |
142 | }
143 |
144 | /**
145 | * Int.gcd
146 | */
147 | it("gcd") {
148 |
149 | expect(3.gcd(6)) == 3
150 |
151 | expect(6.gcd(3)) == 3
152 |
153 | expect(6124.gcd(342)) == 2
154 |
155 | expect(342.gcd(6124)) == 2
156 |
157 | }
158 |
159 | /**
160 | * Int.lcm
161 | */
162 | it("lcm") {
163 |
164 | expect(3.lcm(4)) == 12
165 |
166 | expect(4.lcm(3)) == 12
167 |
168 | }
169 |
170 | /**
171 | * Int.abs
172 | */
173 | it("abs") {
174 |
175 | expect((-1).abs()) == 1
176 | expect((-10).abs()) == 10
177 |
178 | expect(1.abs()) == 1
179 |
180 | expect(0.abs()) == 0
181 |
182 | }
183 |
184 | describe("time") {
185 |
186 | it("years") {
187 |
188 | expect(0.years) == 0
189 | expect(1.year) == 31536000
190 | expect(111.years) == 31536000 * 111
191 |
192 | expect(-1.year) == -31536000
193 | expect(-111.years) == -31536000 * 111
194 |
195 | expect(0.year) == 0.years
196 | expect(1.year) == 1.years
197 | expect(1010.year) == 1010.years
198 |
199 | }
200 |
201 | it("days") {
202 |
203 | expect(0.days) == 0
204 | expect(1.day) == 86400
205 | expect(111.days) == 86400 * 111
206 |
207 | expect(-1.day) == -86400
208 | expect(-111.days) == -86400 * 111
209 |
210 | expect(0.day) == 0.days
211 | expect(1.day) == 1.days
212 | expect(1010.day) == 1010.days
213 |
214 | }
215 |
216 | it("hours") {
217 |
218 | expect(0.hours) == 0
219 | expect(1.hour) == 3600
220 | expect(111.hours) == 3600 * 111
221 |
222 | expect(-1.hour) == -3600
223 | expect(-111.hours) == -3600 * 111
224 |
225 | expect(0.hour) == 0.hours
226 | expect(1.hour) == 1.hours
227 | expect(1010.hour) == 1010.hours
228 |
229 | }
230 |
231 | it("minutes") {
232 |
233 | expect(0.minutes) == 0
234 | expect(1.minute) == 60
235 | expect(111.minutes) == 60 * 111
236 |
237 | expect(-1.minute) == -60
238 | expect(-111.minutes) == -60 * 111
239 |
240 | expect(0.minute) == 0.minutes
241 | expect(1.minute) == 1.minutes
242 | expect(1010.minute) == 1010.minutes
243 |
244 | }
245 |
246 | it("seconds") {
247 |
248 | expect(0.seconds) == 0
249 | expect(1.second) == 1
250 | expect(111.seconds) == 111
251 |
252 | expect(-1.second) == -1
253 | expect(-111.seconds) == -111
254 |
255 | expect(0.second) == 0.seconds
256 | expect(1.second) == 1.seconds
257 | expect(1010.second) == 1010.seconds
258 |
259 | }
260 |
261 | }
262 |
263 | }
264 |
265 | }
266 |
--------------------------------------------------------------------------------
/ExSwiftTests/NSArrayExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSArrayExtensionsTests.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 10/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 |
12 | class NSArrayExtensionsSpec: QuickSpec {
13 |
14 | override func spec() {
15 |
16 | it("cast") {
17 |
18 | let array: NSArray = ["A", 10, "B", "C", false]
19 |
20 | expect(array.cast() as [NSNumber]) == [10, 0]
21 | expect(array.cast() as [NSString]) == ["A", "B", "C"]
22 |
23 | expect(array.cast() as [Int]) == [10, 0]
24 |
25 | }
26 |
27 | it("flatten") {
28 |
29 | let array = [5, [6, ["A", 7]], 8]
30 |
31 | expect(array.flatten() as [NSNumber]) == [5, 6, 7, 8]
32 | expect(array.flatten() as [Int]) == [5, 6, 7, 8]
33 | expect(array.flatten() as [String]) == ["A"]
34 |
35 | expect(array.flattenAny() as? [NSObject]) == [5, 6, "A", 7, 8]
36 |
37 | }
38 |
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/ExSwiftTests/NSDateExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSDateExtensionsTests.swift
3 | // ExSwift
4 | //
5 | // Created by Piergiuseppe Longo on 23/11/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 |
12 | class NSDateExtensionsSpec: QuickSpec {
13 |
14 | let dateFormatter = NSDateFormatter()
15 |
16 | var startDate: NSDate?
17 |
18 | override func spec() {
19 |
20 | beforeSuite {
21 |
22 | self.dateFormatter.dateFormat = "dd/MM/yyyy HH:mm:ss"
23 |
24 | }
25 |
26 | beforeEach {
27 |
28 | self.startDate = self.dateFormatter.dateFromString("30/11/1988 00:00:00")
29 |
30 | }
31 |
32 | describe("manipulation") {
33 |
34 | it("addSeconds") {
35 |
36 | var expectedDate = self.dateFormatter.dateFromString("30/11/1988 00:00:42")
37 |
38 | expect(self.startDate?.addSeconds(42)) == expectedDate
39 | expect(self.startDate?.add(seconds: 42)) == expectedDate
40 |
41 | expectedDate = self.dateFormatter.dateFromString("29/11/1988 23:59:18")
42 |
43 | expect(self.startDate?.addSeconds(-42)) == expectedDate
44 | expect(self.startDate?.add(seconds: -42)) == expectedDate
45 |
46 | }
47 |
48 | it("addMinutes") {
49 |
50 | var expectedDate = self.dateFormatter.dateFromString("30/11/1988 00:42:00")
51 |
52 | expect(self.startDate?.addMinutes(42)) == expectedDate
53 | expect(self.startDate?.add(minutes: 42)) == expectedDate
54 |
55 | expectedDate = self.dateFormatter.dateFromString("29/11/1988 23:18:00")
56 |
57 | expect(self.startDate?.addMinutes(-42)) == expectedDate
58 | expect(self.startDate?.add(minutes: -42)) == expectedDate
59 |
60 | }
61 |
62 | it("addHours") {
63 |
64 | var expectedDate = self.dateFormatter.dateFromString("01/12/1988 18:00:00")
65 |
66 | expect(self.startDate?.addHours(42)) == expectedDate
67 | expect(self.startDate?.add(hours: 42)) == expectedDate
68 |
69 | expectedDate = self.dateFormatter.dateFromString("28/11/1988 06:00:00")
70 |
71 | expect(self.startDate?.addHours(-42)) == expectedDate
72 | expect(self.startDate?.add(hours: -42)) == expectedDate
73 |
74 | }
75 |
76 | it("addDays") {
77 |
78 | var expectedDate = self.dateFormatter.dateFromString("02/12/1988 00:00:00")
79 |
80 | expect(self.startDate?.addDays(2)) == expectedDate
81 | expect(self.startDate?.add(days: 2)) == expectedDate
82 |
83 | expectedDate = self.dateFormatter.dateFromString("19/10/1988 00:00:00")
84 |
85 | expect(self.startDate?.addDays(-42)) == expectedDate
86 | expect(self.startDate?.add(days: -42)) == expectedDate
87 |
88 | }
89 |
90 | it("addWeeks") {
91 |
92 | var expectedDate = self.dateFormatter.dateFromString("7/12/1988 00:00:00")
93 |
94 | expect(self.startDate?.addWeeks(1)) == expectedDate
95 | expect(self.startDate?.add(weeks: 1)) == expectedDate
96 |
97 | expectedDate = self.dateFormatter.dateFromString("23/11/1988 00:00:00")
98 |
99 | expect(self.startDate?.addWeeks(-1)) == expectedDate
100 | expect(self.startDate?.add(weeks: -1)) == expectedDate
101 |
102 | }
103 |
104 | it("addMonths") {
105 |
106 | var expectedDate = self.dateFormatter.dateFromString("30/12/1988 00:00:00")
107 |
108 | expect(self.startDate?.addMonths(1)) == expectedDate
109 | expect(self.startDate?.add(months: 1)) == expectedDate
110 |
111 | expectedDate = self.dateFormatter.dateFromString("30/10/1988 00:00:00")
112 |
113 | expect(self.startDate?.addMonths(-1)) == expectedDate
114 | expect(self.startDate?.add(months: -1)) == expectedDate
115 |
116 | }
117 |
118 | it("addYears") {
119 |
120 | var expectedDate = self.dateFormatter.dateFromString("30/11/1989 00:00:00")
121 |
122 | expect(self.startDate?.addYears(1)) == expectedDate
123 | expect(self.startDate?.add(years: 1)) == expectedDate
124 |
125 | expectedDate = self.dateFormatter.dateFromString("30/11/1987 00:00:00")
126 |
127 | expect(self.startDate?.addYears(-1)) == expectedDate
128 | expect(self.startDate?.add(years: -1)) == expectedDate
129 |
130 | }
131 |
132 | it("add") {
133 |
134 | var expectedDate = self.dateFormatter.dateFromString("10/01/1990 18:42:42")
135 |
136 | expect(self.startDate?.add(seconds: 42, minutes: 42, hours: 42, days: 2, weeks: 1 , months: 1, years: 1)) == expectedDate
137 |
138 | expectedDate = self.dateFormatter.dateFromString("20/10/1987 22:17:18")
139 |
140 | expect(self.startDate?.add(seconds: -42, minutes: -42, hours: -1, days: -2, weeks: -1 , months: -1, years: -1)) == expectedDate
141 |
142 | }
143 |
144 | }
145 |
146 | describe("comparison") {
147 |
148 | it("isAfter") {
149 |
150 | let date = NSDate()
151 |
152 | var futureDate = date.addSeconds(42)
153 | var pastDate = date.addSeconds(-42)
154 |
155 | expect(futureDate.isAfter(date)).to(beTrue())
156 | expect(date.isAfter(date)).to(beFalse())
157 | expect(pastDate.isAfter(date)).to(beFalse())
158 |
159 | }
160 |
161 | it("isBefore") {
162 |
163 | let date = NSDate()
164 |
165 | var futureDate = date.addSeconds(42)
166 | var pastDate = date.addSeconds(-42)
167 |
168 | expect(futureDate.isBefore(date)).to(beFalse())
169 | expect(date.isBefore(date)).to(beFalse())
170 | expect(pastDate.isBefore(date)).to(beTrue())
171 |
172 | }
173 |
174 | }
175 |
176 | it("components properties") {
177 |
178 | expect(self.startDate!.year) == 1988
179 | expect(self.startDate!.month) == 11
180 | expect(self.startDate!.days) == 30
181 | expect(self.startDate!.hours) == 0
182 | expect(self.startDate!.minutes) == 0
183 | expect(self.startDate!.seconds) == 0
184 | expect(self.startDate!.weekday) == 4
185 | expect(self.startDate!.weekMonth) == 5
186 |
187 | }
188 |
189 | describe("comparable") {
190 |
191 | it("sorting") {
192 |
193 | let firstDate = self.startDate!.addSeconds(0)
194 | let secondDate = self.startDate!.addSeconds(42)
195 | let thirdDate = self.startDate!.addSeconds(-42)
196 | let fourthDate = self.startDate!.addSeconds(-84)
197 | let fifthDate = self.startDate!.addSeconds(84)
198 |
199 | var dates = [thirdDate, secondDate, firstDate, fourthDate, fifthDate]
200 |
201 | let expected = [fifthDate, secondDate, firstDate, thirdDate, fourthDate]
202 | let expectedReverded = expected.reverse()
203 |
204 | for i in 0 ... 42 {
205 | dates.shuffle()
206 |
207 | dates.sort( { $0 > $1 } )
208 | expect(dates) == expected
209 |
210 | dates.sort( { $0 < $1 } )
211 | expect(dates) == expectedReverded
212 | }
213 |
214 | }
215 |
216 | it("comparable") {
217 |
218 | let date = self.startDate!.addSeconds(-42)
219 | let anotherDate = self.startDate!.addSeconds(42)
220 | let shouldBeTheSameDate = NSDate(timeInterval: 0, sinceDate: self.startDate!)
221 |
222 | expect(self.startDate) == shouldBeTheSameDate
223 |
224 | expect(self.startDate) > date
225 | expect(self.startDate) >= date
226 |
227 | expect(self.startDate) <= anotherDate
228 | expect(self.startDate) < anotherDate
229 |
230 | expect(date) != self.startDate
231 | expect(anotherDate) != self.startDate
232 |
233 | }
234 |
235 | }
236 |
237 | it("arithmetic") {
238 |
239 | let date = NSDate() as NSDate
240 |
241 | expect(date.timeIntervalSinceDate(date - 1.hour)) == 1.hour
242 | expect(date.timeIntervalSinceDate(date + 1.hour)) == -1.hour
243 |
244 | var otherDate = date
245 |
246 | otherDate -= 1.minute
247 | expect(otherDate) !== date
248 | expect(date.timeIntervalSinceDate(otherDate)) == 1.minute
249 |
250 | otherDate += 1.hour
251 | expect(date.timeIntervalSinceDate(otherDate)) == 1.minute - 1.hour
252 |
253 | }
254 |
255 | }
256 |
257 | }
258 |
259 |
--------------------------------------------------------------------------------
/ExSwiftTests/RangeExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RangeExtensionsTests.swift
3 | // ExSwift
4 | //
5 | // Created by pNre on 04/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 |
12 | class RangeExtensionsSpec: QuickSpec {
13 |
14 | override func spec() {
15 |
16 | /**
17 | * Range.times
18 | */
19 | it("times") {
20 |
21 | var count: Int = 0
22 | (2..<4).times { count++ }
23 |
24 | expect(count) == 2
25 |
26 | count = 0
27 | (2...4).times { count++ }
28 |
29 | expect(count) == 3
30 |
31 | }
32 |
33 | /**
34 | * Range.each
35 | */
36 | it("each") {
37 |
38 | var items = [Int]()
39 | (0..<2).each(items.append)
40 |
41 | expect(items) == [0, 1]
42 |
43 | (0..<0).each { (current: Int) in
44 | fail()
45 | }
46 |
47 | }
48 |
49 | }
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/ExSwiftTests/SequenceExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SequenceExtensionsTests.swift
3 | // ExSwift
4 | //
5 | // Created by Colin Eberhardt on 24/06/2014.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 |
10 | import Quick
11 | import Nimble
12 |
13 | class SequenceExtensionsSpec: QuickSpec {
14 |
15 | var sequence = 1...5
16 | var emptySequence = 1..<1
17 |
18 | override func spec() {
19 |
20 | it("first") {
21 |
22 | expect(SequenceOf(self.sequence).first) == 1
23 |
24 | expect(SequenceOf(self.emptySequence).first).to(beNil())
25 |
26 | }
27 |
28 | it("contains") {
29 |
30 | expect(SequenceOf(self.sequence).contains(1)).to(beTrue())
31 | expect(SequenceOf(self.sequence).contains(56)).to(beFalse())
32 |
33 | }
34 |
35 | it("indexOf") {
36 |
37 | expect(SequenceOf(self.sequence).indexOf(2)) == 1
38 | expect(SequenceOf(self.sequence).indexOf(56)).to(beNil())
39 |
40 | }
41 |
42 | it("skip") {
43 |
44 | expect(Array(SequenceOf(self.sequence).skip(0))) == Array(SequenceOf(self.sequence))
45 |
46 | expect(Array(SequenceOf(self.sequence).skip(2))) == [3, 4, 5]
47 |
48 | expect(Array(SequenceOf(self.sequence).skip(8))) == []
49 |
50 | }
51 |
52 | it("skipWhile") {
53 |
54 | expect(Array(SequenceOf(self.sequence).skipWhile { $0 < 3 })) == [3, 4, 5]
55 |
56 | expect(Array(SequenceOf(self.sequence).skipWhile { $0 < 20 })) == []
57 |
58 | }
59 |
60 | it("take") {
61 |
62 | expect(Array(SequenceOf(self.sequence).take(0))) == []
63 |
64 | expect(Array(SequenceOf(self.sequence).take(2))) == [1, 2]
65 |
66 | expect(Array(SequenceOf(self.sequence).take(20))) == Array(SequenceOf(self.sequence))
67 |
68 | }
69 |
70 | it("takeWhile") {
71 |
72 | expect(Array(SequenceOf(self.sequence).takeWhile { $0 != 3 })) == [1, 2]
73 |
74 | expect(Array(SequenceOf(self.sequence).takeWhile { $0 == 7 })) == []
75 |
76 | expect(Array(SequenceOf(self.sequence).takeWhile { $0 != 7 })) == [1, 2, 3, 4, 5]
77 |
78 | }
79 |
80 | describe("get") {
81 |
82 | it("index") {
83 |
84 | expect(SequenceOf(self.sequence).get(3)) == 3
85 | expect(SequenceOf(self.sequence).get(22)).to(beNil())
86 |
87 | }
88 |
89 | it("range") {
90 |
91 | expect(Array(SequenceOf(self.sequence).get(1..<3))) == [2, 3]
92 |
93 | expect(Array(SequenceOf(self.sequence).get(0..<0))) == []
94 |
95 | expect(Array(SequenceOf(self.sequence).get(10..<15))) == []
96 |
97 | }
98 |
99 | }
100 |
101 | it("any") {
102 |
103 | expect(SequenceOf(self.sequence).any { $0 == 1 }).to(beTrue())
104 |
105 | expect(SequenceOf(self.sequence).any { $0 == 77 }).to(beFalse())
106 |
107 | }
108 |
109 | it("filter") {
110 |
111 | var evens = SequenceOf(self.sequence).filter { $0 % 2 == 0 }
112 | expect(Array(evens)) == [2, 4]
113 |
114 | var odds = SequenceOf(self.sequence).filter { $0 % 2 == 1 }
115 | expect(Array(odds)) == [1, 3, 5]
116 |
117 | var all = SequenceOf(self.sequence).filter { $0 < 10 }
118 | expect(Array(all)) == [1, 2, 3, 4, 5]
119 |
120 | var none = SequenceOf(self.sequence).filter { $0 > 10 }
121 | expect(Array(none)) == []
122 |
123 | }
124 |
125 | it("reject") {
126 |
127 | var rejected = SequenceOf(self.sequence).reject { $0 == 3 }
128 | expect(Array(rejected)) == [1, 2, 4, 5]
129 |
130 | rejected = SequenceOf(self.sequence).reject { $0 == 1 }
131 | expect(Array(rejected)) == [2, 3, 4, 5]
132 |
133 | rejected = SequenceOf(self.sequence).reject { $0 == 10 }
134 | expect(Array(rejected)) == [1, 2, 3, 4, 5]
135 |
136 | }
137 |
138 | }
139 |
140 | }
141 |
--------------------------------------------------------------------------------
/ExSwiftTests/StringExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StringExtensionsTests.swift
3 | // ExSwift
4 | //
5 | // Created by ExSwift on 04/06/14.
6 | // Copyright (c) 2014 pNre. All rights reserved.
7 | //
8 |
9 | import Quick
10 | import Nimble
11 |
12 | class StringExtensionsSpec: QuickSpec {
13 |
14 | override func spec() {
15 |
16 | /**
17 | * String.length
18 | */
19 | it("length") {
20 |
21 | expect("".length) == 0
22 | expect("A".length) == 1
23 | expect("😱".length) == 1
24 | expect("∞".length) == 1
25 | expect("∞aA".length) == 3
26 |
27 | }
28 |
29 | /**
30 | * String[x]
31 | */
32 | it("subscript") {
33 |
34 | let string = "∆Test😗"
35 |
36 | expect(string[0]) == "∆"
37 | expect(string[1]) == "T"
38 |
39 | expect(string[string.length - 1]) == "😗"
40 | expect(string[1..<6]) == "Test😗"
41 |
42 | if let s = "hello"[0] {
43 | expect(s) == "h"
44 | } else {
45 | fail("string[0]")
46 | }
47 |
48 | expect("ABCD"[0, 2]) == ["A", "C"]
49 |
50 | }
51 |
52 | /**
53 | * String.at
54 | */
55 | it("at") {
56 |
57 | expect("ABCD".at(0)) == ["A"]
58 | expect("ABCD".at(0)) == ["ABCD"[0]!]
59 |
60 | expect("ABCD".at(0, 2)) == ["A", "C"]
61 | expect("ABCD".at(0, 2)) == "ABCD"[0, 2]
62 |
63 | }
64 |
65 | /**
66 | * String.explode
67 | */
68 | it("explode") {
69 |
70 | expect("A B C".explode(" ")) == ["A", "B", "C"]
71 |
72 | expect("A B C".explode(">")) == ["A B C"]
73 | expect("A>B C".explode(">")) == ["A", "B C"]
74 |
75 | }
76 |
77 | /**
78 | * String.capitalized
79 | */
80 | it("capitalized") {
81 |
82 | expect("".capitalized) == ""
83 | expect("abcdef".capitalized) == "Abcdef"
84 | expect("Abcdef".capitalized) == "Abcdef"
85 |
86 | }
87 |
88 | /**
89 | * String.insert
90 | */
91 | it("insert") {
92 |
93 | expect("abcdef".insert(0, "X")) == "Xabcdef"
94 |
95 | expect("abcdef".insert(10, "X")) == "abcdefX"
96 | expect("abcdef".insert(3, "X")) == "abcXdef"
97 |
98 | }
99 |
100 | /**
101 | * String.repeat
102 | */
103 | it("repeat operator") {
104 |
105 | expect("A" * 3) == "AAA"
106 | expect("A" * 0) == ""
107 |
108 | }
109 |
110 | /**
111 | * String pattern matching
112 | */
113 | describe("matching") {
114 |
115 | it("=~") {
116 |
117 | let string = "ABcd"
118 |
119 | expect(string =~ "^A").to(beTrue())
120 |
121 | expect(string =~ (pattern: "D$", ignoreCase: true)).to(beTrue())
122 | expect(string =~ "D$").to(beFalse())
123 |
124 | // String[] all
125 | let strings = [string, string, string]
126 |
127 | expect(strings =~ "^A").to(beTrue())
128 |
129 | expect(strings =~ (pattern: "D$", ignoreCase: true)).to(beTrue())
130 | expect(strings =~ "D$").to(beFalse())
131 |
132 | }
133 |
134 | it("|~") {
135 |
136 | // String[] any
137 | let strings = ["ABcd", "ABcd", "ABcd"]
138 |
139 | XCTAssertTrue(strings |~ "^A")
140 |
141 | XCTAssertTrue(strings |~ (pattern: "D$", ignoreCase: true))
142 | XCTAssertFalse(strings |~ "D$")
143 |
144 | }
145 |
146 | it("matches") {
147 |
148 | let string = "AB[31]"
149 |
150 | let matches = string.matches("\\d+")!
151 | let range = matches[0].rangeAtIndex(0)
152 |
153 | let substringRange = range.location..<(range.location + range.length)
154 |
155 | expect(string[substringRange]) == "31"
156 | expect(string.matches("N")!.isEmpty).to(beTrue())
157 |
158 | }
159 |
160 | }
161 |
162 |
163 | /**
164 | * String contains matches
165 | */
166 | describe("containsMatch checks"){
167 | it("match") {
168 | expect("Test string for match".containsMatch("for")).to(beTrue())
169 | }
170 | it("not match") {
171 | expect("Test string for match".containsMatch("not for")).to(beFalse())
172 | }
173 | }
174 |
175 | /**
176 | * ReplaceMatches in string
177 | */
178 | describe("ReplaceMatches checks"){
179 | it("find match to replace") {
180 | expect("Test_string".replaceMatches("_.*", withString: "_replace")) == "Test_replace"
181 | }
182 |
183 | it("find match to replacei with empty string") {
184 | expect("Test 111string 222for333 match".replaceMatches("\\d+", withString: "")) == "Test string for match"
185 | }
186 |
187 | it("not find match to replace") {
188 | expect("Test string for match".replaceMatches("\\d+", withString: "some string")) == "Test string for match"
189 | }
190 | }
191 |
192 | /**
193 | * String trimming methods
194 | */
195 | describe("trimming") {
196 |
197 | it("trimmed") {
198 |
199 | expect("t e".trimmed()) == "t e"
200 | expect(" AB".trimmed()) == "AB"
201 | expect("\n ABC ".trimmed()) == "ABC"
202 | expect("".trimmed()) == ""
203 | expect(" \t\n\r".trimmed()) == ""
204 |
205 | }
206 |
207 | describe("trimmedLeft") {
208 |
209 | it("default character set") {
210 |
211 | expect("ab ".trimmedLeft()) == "ab "
212 | expect("ab".trimmedLeft()) == "ab"
213 | expect(" AB".trimmedLeft()) == "AB"
214 | expect("\n ABC ".trimmedLeft()) == "ABC "
215 | expect("".trimmedLeft()) == ""
216 | expect(" \t\n\r".trimmedLeft()) == ""
217 |
218 | }
219 |
220 | it("with character set") {
221 |
222 | expect("ab ".trimmedLeft(characterSet: NSCharacterSet.alphanumericCharacterSet())) == " "
223 | expect(" ab".trimmedLeft(characterSet: NSCharacterSet.alphanumericCharacterSet())) == " ab"
224 | expect("ab".trimmedLeft(characterSet: NSCharacterSet.alphanumericCharacterSet())) == ""
225 |
226 | }
227 |
228 | }
229 |
230 | describe("trimmedRight") {
231 |
232 | it("default character set") {
233 |
234 | expect("t e".trimmedRight()) == "t e"
235 | expect(" AB".trimmedRight()) == " AB"
236 | expect("AB ".trimmedRight()) == "AB"
237 | expect("\n ABC ".trimmedRight()) == "\n ABC"
238 | expect("".trimmedRight()) == ""
239 | expect(" \t\n\r".trimmedRight()) == ""
240 |
241 | }
242 |
243 | it("with character set") {
244 |
245 | expect("ab ".trimmedRight(characterSet: NSCharacterSet.alphanumericCharacterSet())) == "ab "
246 | expect(" ab".trimmedRight(characterSet: NSCharacterSet.alphanumericCharacterSet())) == " "
247 | expect("ab".trimmedRight(characterSet: NSCharacterSet.alphanumericCharacterSet())) == ""
248 |
249 | }
250 |
251 | }
252 |
253 | describe("type conversion") {
254 |
255 | it("toDouble") {
256 |
257 | expect(" 7.2 ".toDouble()).to(beCloseTo(7.2, within: 0.0001))
258 | expect("-70.211111 ".toDouble()).to(beCloseTo(-70.211111, within: 0.0001))
259 | expect("42".toDouble()).to(beCloseTo(42, within: 0.0001))
260 |
261 | expect("a772.2".toDouble()).to(beNil())
262 |
263 | }
264 |
265 | it("toFloat") {
266 |
267 | expect(" 7.2 ".toFloat()).to(beCloseTo(7.2, within: 0.0001))
268 | expect("-70.211111 ".toFloat()).to(beCloseTo(-70.211111, within: 0.0001))
269 | expect("42".toFloat()).to(beCloseTo(42, within: 0.0001))
270 |
271 | expect("a772.2".toFloat()).to(beNil())
272 |
273 | }
274 |
275 | it("toUInt") {
276 |
277 | expect(" 7 ".toUInt()) == 7
278 |
279 | expect("a772.2".toUInt()).to(beNil())
280 | expect("-772".toUInt()).to(beNil())
281 | expect("7.5".toUInt()).to(beNil())
282 |
283 | }
284 |
285 | it("toBool") {
286 |
287 | expect(" TrUe ".toBool()).to(beTrue())
288 | expect(" yEs ".toBool()).to(beTrue())
289 |
290 | expect(" FALSE ".toBool()).to(beFalse())
291 | expect(" nO ".toBool()).to(beFalse())
292 |
293 | expect("".toBool()).to(beNil())
294 | expect("jeff".toBool()).to(beNil())
295 | expect("0".toBool()).to(beNil())
296 |
297 | }
298 |
299 | it("toDate") {
300 |
301 | var d : NSDate = " 2015-08-19 \t ".toDate()!
302 |
303 | var c = NSDateComponents()
304 | c.year = 2015
305 | c.month = 8
306 | c.day = 19
307 |
308 | var gregorian = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
309 | expect(gregorian.dateFromComponents(c)) == d
310 |
311 | expect("a772.2".toDate()).to(beNil())
312 | expect("Tuesday".toDate()).to(beNil())
313 | expect("1973-08-19 03:04:55".toDate()).to(beNil())
314 |
315 | }
316 |
317 | it("toDateTime") {
318 |
319 | var d : NSDate = " 2015-08-19 03:04:34\t ".toDateTime()!
320 |
321 | var c = NSDateComponents()
322 | c.year = 2015
323 | c.month = 8
324 | c.day = 19
325 | c.hour = 3
326 | c.minute = 4
327 | c.second = 34
328 |
329 | var gregorian = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
330 | expect(gregorian.dateFromComponents(c)) == d
331 |
332 | expect("a772.2".toDateTime()).to(beNil())
333 | expect("Tuesday".toDateTime()).to(beNil())
334 | expect("1973-08-19".toDateTime()).to(beNil())
335 |
336 | }
337 |
338 | }
339 |
340 | /**
341 | * String.random
342 | */
343 | it("random") {
344 |
345 | expect(String.random().length).to(beLessThanOrEqualTo(16))
346 | expect(String.random(length: 12).length) == 12
347 |
348 | }
349 |
350 | }
351 |
352 | }
353 |
354 | }
355 |
356 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014, pNre
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 |
24 | The views and conclusions contained in the software and documentation are those
25 | of the authors and should not be interpreted as representing official policies,
26 | either expressed or implied, of the FreeBSD Project.
27 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | inhibit_all_warnings!
2 | use_frameworks!
3 |
4 | def import_test_pods
5 |
6 | pod 'Quick', '~> 0.3.1'
7 | pod 'Nimble', '~> 0.4.2'
8 |
9 | end
10 |
11 | target "ExSwiftTests-iOS" do
12 |
13 | platform :ios, '8.0'
14 |
15 | import_test_pods
16 |
17 | end
18 |
19 | target "ExSwiftTests-Mac" do
20 |
21 | platform :osx, '10.10'
22 |
23 | import_test_pods
24 |
25 | end
26 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Nimble (0.4.2)
3 | - Quick (0.3.1)
4 |
5 | DEPENDENCIES:
6 | - Nimble (~> 0.4.2)
7 | - Quick (~> 0.3.1)
8 |
9 | SPEC CHECKSUMS:
10 | Nimble: 49b7a7da8919f42823d37c6d68cc6d15a7009f32
11 | Quick: 824572d3d198d51e52cf4aa722cebf7e59952a35
12 |
13 | COCOAPODS: 0.37.1
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ExSwift
2 |  [](https://github.com/Carthage/Carthage) [](https://travis-ci.org/pNre/ExSwift)
3 |
4 | Set of Swift extensions for standard types and classes.
5 |
6 | # Installation
7 |
8 | Because of Xcode errors it's not possible to integrate this project with Cocoapods or as Embedded Framework.
9 | [Read more at Dev Forum](https://devforums.apple.com/message/983747#983747)
10 |
11 | ## Use submodule and copy source code
12 | 1. Add ExSwift as a submodule
13 | 2. Open the `ExSwift` project folder, and drag `ExSwift` sub folder with source code into the file navigator of your Xcode project. Make sure you select add to target
14 | 3. Use it
15 |
16 | ``` swift
17 | components.takeFirst() { $0.completed }
18 | ```
19 |
20 | ## Contents ##
21 |
22 | - [ExSwift extensions](#extensions)
23 | - [Array](#array)
24 | - [Instance Methods](#instance-methods)
25 | - [Class Methods](#class-methods)
26 | - [Operators](#operators)
27 | - [Int](#int)
28 | - [Properties](#properties)
29 | - [Instance Methods](#instance-methods-1)
30 | - [Class Methods](#class-methods-1)
31 | - [Float](#float)
32 | - [Instance Methods](#instance-methods-2)
33 | - [Class Methods](#class-methods-2)
34 | - [String](#string)
35 | - [Properties](#properties-1)
36 | - [Instance Methods](#instance-methods-3)
37 | - [Class Methods](#class-methods-3)
38 | - [Operators](#operators-1)
39 | - [Range](#range)
40 | - [Instance Methods](#instance-methods-4)
41 | - [Class Methods](#class-methods-4)
42 | - [Operators](#operators-2)
43 | - [Dictionary](#dictionary)
44 | - [Instance Methods](#instance-methods-5)
45 | - [Operators](#operators-3)
46 | - [NSArray](#nsarray)
47 | - [Instance Methods](#instance-methods-6)
48 | - [SequenceOf](#sequenceof)
49 | - [Instance Methods](#instance-methods-7)
50 | - [Double](#double)
51 | - [Instance Methods](#instance-methods-8)
52 | - [Class Methods](#class-methods-5)
53 | - [NSDate](#nsdate)
54 | - [Instance Methods](#instance-methods-9)
55 | - [Operators](#operators-4)
56 |
57 | - [Utilities](#utilities)
58 | - [Class Methods](#class-methods-6)
59 | - [Operators](#operators-5)
60 |
61 | # Extensions #
62 |
63 | ## Array ##
64 |
65 | Examples in the [Wiki](https://github.com/pNre/ExSwift/wiki/Array)
66 |
67 | #### Instance Methods ####
68 |
69 | Name | Signature
70 | ---- | ---------
71 | **`first`**|`first () -> Element?`
72 | **`last`**|`last () -> Element?`
73 | **`get`**|`get (index: Int) -> Element?`
74 | **`remove`**|`remove (element: U)`
75 | **`at`**|`at (indexes: Int...) -> Array`
76 | **`take`**|`take (n: Int) -> Array`
77 | **`takeWhile`**|`takeWhile (condition: (Element) -> Bool) -> Array`
78 | **`takeFirst`**|`takeFirst (condition: (Element) -> Bool) -> Element?`
79 | **`tail`**|`tail (n: Int) -> Array`
80 | **`skip`**|`skip (n: Int) -> Array`
81 | **`skipWhile`**|`skipWhile (condition: (Element) -> Bool) -> Array`
82 | **`contains`**|`contains (item: T...) -> Bool`
83 | **`difference`**|`difference (values: [T]...) -> [T]`
84 | **`intersection`**|`intersection (values: [U]...) -> Array`
85 | **`union`**|`union (values: [U]...) -> Array`
86 | **`unique`**|`unique () -> [T]`
87 | **`indexOf`**|`indexOf (item: T) -> Int?`
88 | **`indexOf`**|`indexOf (condition: Element -> Bool) -> Int?`
89 | **`lastIndexOf`**|`lastIndexOf (item: T) -> Int?`
90 | **`zip`**|`zip (arrays: Array...) -> [[Any?]]`
91 | **`partition`**|`partition (var n: Int, var step: Int? = nil) -> [Array]`
`partition (var n: Int, var step: Int? = nil, pad: Element[]?) -> [Array]`
92 | **`partitionAll`**|`partitionAll (var n: Int, var step: Int? = nil) -> [Array]`
93 | **`partitionBy`**|`partitionBy (cond: (Element) -> T) -> [Array]`
94 | **`shuffle`**|`shuffle ()`
95 | **`shuffled`**|`shuffled () -> Array`
96 | **`sample`** *(random)*|`sample (size n: Int = 1) -> [T]`
97 | **`max`**|`max () -> T`
98 | **`min`**|`min () -> T`
99 | **`each`**|`each (call: (Element) -> ())`
`each (call: (Int, Element) -> ())`
100 | **`eachRight`**|`eachRight (call: (Element) -> ())`
`eachRight (call: (Int, Element) -> ())`
101 | **`any`**|`any (call: (Element) -> Bool) -> Bool`
102 | **`all`**|`all (call: (Element) -> Bool) -> Bool`
103 | **`reject`**|`reject (exclude: (Element -> Bool)) -> Array`
104 | **`pop`**|`pop() -> Element`
105 | **`push`**|`push(newElement: Element)`
106 | **`shift`**|`shift() -> Element`
107 | **`unshift`**|`unshift(newElement: Element)`
108 | **`insert`**|`insert (newArray: Array, atIndex: Int)`
109 | **`groupBy`**|`groupBy (groupingFunction group: (Element) -> (U)) -> [U: Array]`
110 | **`countBy`**|`countBy (groupingFunction group: (Element) -> (U)) -> [U: Int]`
111 | **`countWhere`**|`countWhere (test: (Element) -> Bool) -> Int`
112 | **`reduce`**|`reduce (combine: (Element, Element) -> Element) -> Element?`
113 | **`reduceRight`**|`reduceRight (initial: U, combine: (U, Element) -> U) -> U`
114 | **`mapFilter`**|`mapFilter (mapFunction map: (Element) -> (V)?) -> [V]`
115 | **`implode`**|`implode (separator: C) -> C?`
116 | **`flatten`**|`flatten () -> [OutType]`
117 | **`flattenAny`**|`flattenAny () -> [AnyObject]`
118 | **`toDictionary`**|`toDictionary (keySelector:(Element) -> U) -> [U: Element]`
119 | **`toDictionary`**|`toDictionary (transform: (Element) -> (key: K, value: V)?) -> [K: V]`
120 | **`cycle`**|`cycle (n: Int? = nil, block: (T) -> ())`
121 | **`bSearch`**|`bSearch (block: (T) -> (Bool)) -> T?`
122 | **`bSearch`**|`bSearch (block: (T) -> (Int)) -> T?`
123 | **`sortUsing`**|`sortUsing(block: ((T) -> U)) -> [T]`
124 | **`transposition`**|`transposition (array: [[T]]) -> [[T]]`
125 | **`permutation`**|`permutation (length: Int) -> [[T]]`
126 | **`repeatedPermutation`**|`repeatedPermutation(length: Int) -> [[T]]`
127 | **`combination`**|`combination (length: Int) -> [[Element]]`
128 | **`repeatedCombination `**|`repeatedCombination (length: Int) -> [[Element]]`
129 |
130 | #### Class Methods ####
131 |
132 | Name | Signatures
133 | ---- | ----------
134 | **`range`**|`range (range: Range) -> Array`
135 |
136 | #### Operators ####
137 | Name | Signature | Function
138 | ---- | --------- | --------
139 | `-`|`- (first: Array, second: Array) -> Array`|Difference
140 | `-`|`- (first: Array, second: T) -> Array`|Element removal
141 | `&`|`& (first: Array, second: Array) -> Array`|Intersection
142 | |
|| (first: Array, second: Array) -> Array
|Union
143 | `* Int`|`* (array: ItemType[], n: Int) -> [ItemType]`|Returns a new array built by concatenating int copies of self
144 | `* String`|`* (array: String[], separator: String) -> String`|Equivalent to `array.implode(String)`
145 | `[rangeAsArray: x..y]`
`[rangeAsArray: x...y]`|`subscript(#rangeAsArray: Range) -> Array`|Returns the sub-array from index *x* to index *y*
146 | `[x, y, ...]`|`subscript(first: Int, second: Int, rest: Int...) -> Array`|Returns the items at *x*, *y*
147 |
148 | ## Int ##
149 |
150 | Examples in the [Wiki](https://github.com/pNre/ExSwift/wiki/Int)
151 |
152 | #### Properties ####
153 | Name |
154 | ---- |
155 | `NSTimeInterval`**`years`**|
156 | `NSTimeInterval`**`year`**|
157 | `NSTimeInterval`**`days`**|
158 | `NSTimeInterval`**`day`**|
159 | `NSTimeInterval`**`hours`**|
160 | `NSTimeInterval`**`hour`**|
161 | `NSTimeInterval`**`minutes`**|
162 | `NSTimeInterval`**`minute`**|
163 | `NSTimeInterval`**`seconds`**|
164 | `NSTimeInterval`**`second`**|
165 |
166 | #### Instance Methods ####
167 |
168 | Name | Signatures
169 | ---- | ----------
170 | **`times`**|`times (call: (Int) -> T)`
`times (call: () -> T)`
`times (call: () -> ())`
171 | **`isEven`**|`isEven () -> Bool`
172 | **`isOdd`**|`idOdd () -> Bool`
173 | **`upTo`**|`upTo (limit: Int, call: (Int) -> ())`
174 | **`downTo`**|`downTo (limit: Int, call: (Int) -> ())`
175 | **`clamp`**|`clamp (range: Range) -> Int`
`clamp (min: Int, max: Int) -> Int`
176 | **`isIn`**|`isIn (range: Range, strict: Bool = false) -> Bool`
177 | **`digits`**|`digits () -> Array`
178 | **`abs`**|`abs () -> Int`
179 | **`gcd`**|`gcd (n: Int) -> Int`
180 | **`lcm`**|`lcm (n: Int) -> Int`
181 |
182 | #### Class Methods ####
183 |
184 | Name | Signatures
185 | ---- | ----------
186 | **`random`**|`random(min: Int = 0, max: Int) -> Int`
187 |
188 |
189 | ## Float ##
190 |
191 | Examples in the [Wiki](https://github.com/pNre/ExSwift/wiki/Float)
192 |
193 | #### Instance Methods ####
194 |
195 | Name | Signature
196 | ---- | ---------
197 | **`abs`**|`abs () -> Float`
198 | **`sqrt`**|`sqrt () -> Float`
199 | **`round`**|`round () -> Float`
200 | **`ceil`**|`ceil () -> Float`
201 | **`floor`**|`floor () -> Float`
202 | **`clamp`**|`clamp (min: Float, _ max: Float) -> Float`
203 |
204 | #### Class Methods ####
205 |
206 | Name | Signatures
207 | ---- | ----------
208 | **`random`**|`random(min: Float = 0, max: Float) -> Float`
209 |
210 | ## String ##
211 |
212 | Examples in the [Wiki](https://github.com/pNre/ExSwift/wiki/String)
213 |
214 | #### Properties ####
215 | Name |
216 | ---- |
217 | **`length`**|
218 | **`capitalized`**|
219 |
220 | #### Instance Methods ####
221 |
222 | Name | Signature
223 | ---- | ---------
224 | **`explode`**|`explode (separator: Character) -> [String]`
225 | **`at`**|`at (indexes: Int...) -> [String]`
226 | **`matches`**|`matches (pattern: String, ignoreCase: Bool = false) -> [NSTextCheckingResult]?`
227 | **`insert`**|`insert (index: Int, _ string: String) -> String`
228 | **`ltrimmed`**|`ltrimmed () -> String`
229 | **`ltrimmed`**|`ltrimmed (set: NSCharacterSet) -> String`
230 | **`rtrimmed`**|`rtrimmed () -> String`
231 | **`rtrimmed`**|`rtrimmed (set: NSCharacterSet) -> String`
232 | **`trimmed`**|`trimmed () -> String`
233 | **`rtrimmed`**|`rtrimmed (set: NSCharacterSet) -> String`
234 | **`toDouble`**|`toDouble() -> Double?`
235 | **`toFloat`**|`toFloat() -> Float?`
236 | **`toUInt`**|`toUInt() -> UInt?`
237 | **`toBool`**|`toBool() -> Bool?`
238 | **`toDate`**|`toDate(format : String? = "yyyy-MM-dd") -> NSDate?`
239 | **`toDateTime`**|`toDateTime(format : String? = "yyyy-MM-dd hh-mm-ss") -> NSDate?`
240 |
241 |
242 | #### Class Methods ####
243 |
244 | Name | Signature
245 | ---- | ---------
246 | **`random`**|`func random (var length len: Int = 0, charset: String = "...") -> String`
247 |
248 | #### Operators ####
249 | Name | Signature
250 | ---- | ---------
251 | `[x]`|`subscript(index: Int) -> String?`
252 | `[x..y]`
`[x...y]`|`subscript(range: Range) -> String`
253 | `[x, y, z]`|`subscript (indexes: Int...) -> [String]`
254 | `S * n`|`* (first: String, second: Int) -> String`
255 | `=~`|`=~ (string: String, pattern: String) -> Bool`
`=~ (string: String, options: (pattern: String, ignoreCase: Bool)) -> Bool`
`=~ (strings: [String], pattern: String) -> Bool`
`=~ (strings: [String], options: (pattern: String, ignoreCase: Bool)) -> Bool`
256 | |~
||~ (string: String, pattern: String) -> Bool
|~ (string: String, options: (pattern: String, ignoreCase: Bool)) -> Bool
257 |
258 | ## Range ##
259 |
260 | Examples in the [Wiki](https://github.com/pNre/ExSwift/wiki/Range)
261 |
262 | #### Instance Methods ####
263 |
264 | Name | Signatures
265 | ---- | ----------
266 | **`times`**|`times (call: (T) -> ())`
`times (call: () -> ())`
267 | **`each`**|`each (call: (T) -> ())`
268 | **`toArray`**|`toArray () -> [T]`
269 |
270 | #### Class Methods ####
271 |
272 | Name | Signature
273 | ---- | ---------
274 | **`random`**|`random (from: Int, to: Int) -> Range`
275 |
276 | #### Operators ####
277 | Name | Signature|Function
278 | ---- | ---------|--------
279 | `=`|`== (first: Range, second: Range) -> Bool`|Compares 2 ranges
280 |
281 | ## Dictionary ##
282 |
283 | Examples in the [Wiki](https://github.com/pNre/ExSwift/wiki/Dictionary)
284 |
285 | #### Instance Methods ####
286 |
287 | Name | Signatures
288 | ---- | ----------
289 | **`difference`**|`difference (dictionaries: [Key: V]...) -> [Key: V]`
290 | **`union`**|`union (dictionaries: [Key: Value]...) -> [Key: Value]`
291 | **`intersection`**|`intersection (dictionaries: [K: V]...) -> [K: V]`
292 | **`has`**|`has (key: Key) -> Bool`
293 | **`map`**|`map (mapFunction map: (Key, Value) -> (K, V)) -> [K: V]`
294 | **`mapFilter`**|`mapFilter (mapFunction map: (Key, Value) -> (K, V)?) -> [K: V]`
295 | **`mapValues`**|`mapValues (mapFunction map: (Key, Value) -> (V)) -> [Key: V]`
296 | **`mapFilterValues`**|`mapFilterValues (mapFunction map: (Key, Value) -> V?) -> [Key: V]`
297 | **`each`**|`each(eachFunction each: (Key, Value) -> ())`
298 | **`filter`**|`filter(testFunction test: (Key, Value) -> Bool) -> [Key: Value]`
299 | **`merge`**|`merge (dictionaries: [Key: Value]...) -> [Key: Value]`
300 | **`shift`**|`shift () -> (Key, Value)`
301 | **`groupBy`**|`groupBy (groupingFunction group: (Key, Value) -> (T)) -> [T: Array]`
302 | **`countBy`**|`countBy (groupingFunction group: (Key, Value) -> (T)) -> [T: Int]`
303 | **`countWhere`**|`countWhere (test: (Key, Value) -> (Bool)) -> Int`
304 | **`any`**|`any (test: (Key, Value) -> (Bool)) -> Bool`
305 | **`all`**|`all (test: (Key, Value) -> (Bool)) -> Bool`
306 | **`reduce`**|`reduce (initial: U, combine: (U, Element) -> U) -> U`
307 | **`pick`, `at`**|`pick (keys: [Key]) -> Dictionary`
`pick (keys: Key...) -> Dictionary`
`at (keys: Key...) -> Dictionary`
308 | **`toArray`**|`toArray (mapFunction map: (Key, Value) -> V) -> [V]`
309 |
310 | #### Operators ####
311 | Name | Signature | Function
312 | ---- | --------- | --------
313 | `-`|`- (first: Dictionary, second: Dictionary) -> Dictionary`|Difference
314 | `&`|`& (first: Dictionary, second: Dictionary) -> Dictionary`|Intersection
315 | |
|| (first: Dictionary, second: Dictionary) -> Dictionary
|Union
316 |
317 | ## NSArray ##
318 |
319 | Examples in the [Wiki](https://github.com/pNre/ExSwift/wiki/NSArray)
320 |
321 | #### Instance Methods ####
322 |
323 | Name | Signatures
324 | ---- | ----------
325 | **`cast`**|`cast () -> [OutType]`
326 | **`flatten`**|`flatten () -> [OutType]`
327 | **`flattenAny`**|`flattenAny () -> [AnyObject]`
328 |
329 | ## SequenceOf ##
330 |
331 | The following operations can be performed on sequences and are evaluated lazily. Each operation only takes the data it requires from the source sequence in order to return its result.
332 |
333 | The `Sequence` protocol cannot be extended, hence the following are extensions to `SequenceOf`. They can be used as follows:
334 |
335 | ```
336 | var source: Sequence = ...
337 | var filteredSequence = SequenceOf(source).filter { ... }
338 | ```
339 |
340 | #### Instance Methods ####
341 |
342 | Name | Signatures
343 | ---- | ----------
344 | **`first`**|`first () -> T?`
345 | **`any`**|`any (call: (T) -> Bool) -> Bool`
346 | **`get`**|`get (index: Int) -> T?`
347 | **`get`**|`get (range: Range) -> SequenceOf`
348 | **`indexOf`**|`indexOf (item: U) -> Int?`
349 | **`filter`**|`filter(include: (T) -> Bool) -> SequenceOf`
350 | **`reject`**|`reject (exclude: (T -> Bool)) -> SequenceOf`
351 | **`skipWhile`**|`skipWhile(condition:(T) -> Bool) -> SequenceOf`
352 | **`skip`**|`skip (n:Int) -> SequenceOf`
353 | **`contains`**|`contains (item: T) -> Bool`
354 | **`take`**|`take (n:Int) -> SequenceOf`
355 | **`takeWhile`**|`takeWhile (condition:(T?) -> Bool) -> SequenceOf`
356 |
357 | ## Double ##
358 |
359 | Examples in the [Wiki](https://github.com/pNre/ExSwift/wiki/Double)
360 |
361 | #### Instance Methods ####
362 |
363 | Name | Signature
364 | ---- | ---------
365 | **`abs`**|`abs () -> Double`
366 | **`sqrt`**|`sqrt () -> Double`
367 | **`round`**|`round () -> Double`
368 | **`ceil`**|`ceil () -> Double`
369 | **`floor`**|`floor () -> Double`
370 | **`clamp`**|`clamp (min: Double, _ max: Double) -> Double`
371 | **`roundToNearest`**|`roundToNearest(increment: Double) -> Double`
372 |
373 | #### Class Methods ####
374 |
375 | Name | Signatures
376 | ---- | ----------
377 | **`random`**|`random(min: Double = 0, max: Double) -> Double`
378 |
379 | # NSDate #
380 |
381 | #### Properties ####
382 | Name | Signatures
383 | ---- | ----
384 | **`year`** |`Int`
385 | **`month`**|`Int`
386 | **`weekday`** |`Int`
387 | **`weekMonth`**|`Int`
388 | **`days`** |`Int`
389 | **`hours`**|`Int`
390 | **`minutes`** |`Int`
391 | **`seconds`**| `Int`
392 |
393 | #### Instance Methods ####
394 | Name | Signatures
395 | ---- | ----------
396 | **`add`**|`add(seconds:Int=0, minutes:Int = 0, hours:Int = 0, days:Int = 0, weeks:Int = 0, months:Int = 0, years:Int = 0) -> NSDate`
397 | **`addSeconds`**|`addSeconds (seconds:Int) -> NSDate `
398 | **`addMinutes`**|`addMinutes (minute:Int) -> NSDate `
399 | **`addHours`**|`addHours(hours:Int) -> NSDate `
400 | **`addDays`**|`addDays(days:Int) -> NSDate `
401 | **`addWeeks`**|`addWeeks(weeks:Int) -> NSDate`
402 | **`addMonths`**|`addMonths(months:Int) -> NSDate`
403 | **`addYears`**|`addYears(years:Int) -> NSDate `
404 | **`isAfter`**|`isAfter(date: NSDate) -> Bool`
405 | **`isBefore`**|`isBefore(date: NSDate) -> Bool`
406 | **`getComponent`**|`getComponent (component : NSCalendarUnit) -> Int`
407 |
408 | #### Operators ####
409 |
410 | Name | Signatures
411 | ---- | ----------
412 | **`==`**|`==(lhs: NSDate, rhs: NSDate) -> Bool`
413 | **`<`**|`<(lhs: NSDate, rhs: NSDate) -> Bool`
414 | **`>`**|`>(lhs: NSDate, rhs: NSDate) -> Bool`
415 | **`<=`**|`<=(lhs: NSDate, rhs: NSDate) -> Bool`
416 | **`>=`**|`>=(lhs: NSDate, rhs: NSDate) -> Bool`
417 | **`==`**|`==(lhs: NSDate, rhs: NSDate) -> Bool`
418 |
419 | # Utilities #
420 |
421 | Examples in the [Wiki](https://github.com/pNre/ExSwift/wiki/ExSwift)
422 |
423 | #### Class Methods ####
424 |
425 | Name | Signatures
426 | ---- | ----------
427 | **`after`**|`after (n: Int, function: P -> T) -> (P -> T?)`
`func after (n: Int, function: () -> T) -> (() -> T?)`
428 | **`once`**|`once (function: P -> T) -> (P -> T?)`
`once (call: Void -> T) -> (Void -> T?)`
429 | **`partial`**|`partial (function: (P...) -> T, _ parameters: P...) -> ((P...) -> T?)`
430 | **`bind`**|`bind
(function: (P...) -> T, _ parameters: P...) -> (() -> T)`
431 | **`cached`**|`cached
(function: P -> R) -> (P -> R)`
`cached
(function: (P...) -> R) -> ((P...) -> R)`
`cached
(function: (P...) -> R, hash: ((P...) -> P)) -> ((P...) -> R)`
432 |
433 | #### Operators ####
434 | Name | Signatures
435 | ---- | ----------
436 | **`<=>`**|`<=> (lhs: T, rhs: T) -> Int`
437 |
438 | # To Do #
439 | * [X] Wiki
440 | * [X] Xcode project for both iOS & OS X
441 | * [X] Review code comments
442 | * [ ] Example project
443 | * [ ] Installation instructions
444 | * [ ] Benchmark
445 |
--------------------------------------------------------------------------------