@@ -27,6 +27,7 @@ class TestNSArray : XCTestCase {
27
27
( " test_enumeration " , test_enumeration) ,
28
28
( " test_sequenceType " , test_sequenceType) ,
29
29
( " test_getObjects " , test_getObjects) ,
30
+ ( " test_binarySearch " , test_binarySearch)
30
31
]
31
32
}
32
33
@@ -84,4 +85,67 @@ class TestNSArray : XCTestCase {
84
85
XCTAssertEqual ( fetched, [ " bar " , " baz " , " foo1 " ] )
85
86
}
86
87
88
+ func test_binarySearch( ) {
89
+ let array = NSArray ( array: [
90
+ NSNumber ( int: 0 ) , NSNumber ( int: 1 ) , NSNumber ( int: 2 ) , NSNumber ( int: 2 ) , NSNumber ( int: 3 ) ,
91
+ NSNumber ( int: 4 ) , NSNumber ( int: 4 ) , NSNumber ( int: 6 ) , NSNumber ( int: 7 ) , NSNumber ( int: 7 ) ,
92
+ NSNumber ( int: 7 ) , NSNumber ( int: 8 ) , NSNumber ( int: 9 ) , NSNumber ( int: 9 ) ] )
93
+
94
+ // Not sure how to test fatal errors.
95
+
96
+ // NSArray throws NSInvalidArgument if range exceeds bounds of the array.
97
+ // let rangeOutOfArray = NSRange(location: 5, length: 15)
98
+ // let _ = array.indexOfObject(NSNumber(integer: 9), inSortedRange: rangeOutOfArray, options: [.InsertionIndex, .FirstEqual], usingComparator: compareIntNSNumber)
99
+
100
+ // NSArray throws NSInvalidArgument if both .FirstEqual and .LastEqaul are specified
101
+ // let searchForBoth: NSBinarySearchingOptions = [.FirstEqual, .LastEqual]
102
+ // let _ = objectIndexInArray(array, value: 9, startingFrom: 0, length: 13, options: searchForBoth)
103
+
104
+ let notFound = objectIndexInArray ( array, value: 11 , startingFrom: 0 , length: 13 )
105
+ XCTAssertEqual ( notFound, NSNotFound, " NSArray return NSNotFound if object is not found. " )
106
+
107
+ let notFoundInRange = objectIndexInArray ( array, value: 7 , startingFrom: 0 , length: 5 )
108
+ XCTAssertEqual ( notFoundInRange, NSNotFound, " NSArray return NSNotFound if object is not found. " )
109
+
110
+ let indexOfAnySeven = objectIndexInArray ( array, value: 7 , startingFrom: 0 , length: 13 )
111
+ XCTAssertTrue ( Set ( [ 8 , 9 , 10 ] ) . contains ( indexOfAnySeven) , " If no options provided NSArray returns an arbitrary matching object's index. " )
112
+
113
+ let indexOfFirstNine = objectIndexInArray ( array, value: 9 , startingFrom: 7 , length: 6 , options: [ . FirstEqual] )
114
+ XCTAssertTrue ( indexOfFirstNine == 12 , " If .FirstEqual is set NSArray returns the lowest index of equal objects. " )
115
+
116
+ let indexOfLastTwo = objectIndexInArray ( array, value: 2 , startingFrom: 1 , length: 7 , options: [ . LastEqual] )
117
+ XCTAssertTrue ( indexOfLastTwo == 3 , " If .LastEqual is set NSArray returns the highest index of equal objects. " )
118
+
119
+ let anyIndexToInsertNine = objectIndexInArray ( array, value: 9 , startingFrom: 0 , length: 13 , options: [ . InsertionIndex] )
120
+ XCTAssertTrue ( Set ( [ 12 , 13 , 14 ] ) . contains ( anyIndexToInsertNine) , " If .InsertionIndex is specified and no other options provided NSArray returns any equal or one larger index than any matching object’s index. " )
121
+
122
+ let lowestIndexToInsertTwo = objectIndexInArray ( array, value: 2 , startingFrom: 0 , length: 5 , options: [ . InsertionIndex, . FirstEqual] )
123
+ XCTAssertTrue ( lowestIndexToInsertTwo == 2 , " If both .InsertionIndex and .FirstEqual are specified NSArray returns the lowest index of equal objects. " )
124
+
125
+ let highestIndexToInsertNine = objectIndexInArray ( array, value: 9 , startingFrom: 7 , length: 6 , options: [ . InsertionIndex, . LastEqual] )
126
+ XCTAssertTrue ( highestIndexToInsertNine == 13 , " If both .InsertionIndex and .LastEqual are specified NSArray returns the index of the least greater object... " )
127
+
128
+ let indexOfLeastGreaterObjectThanFive = objectIndexInArray ( array, value: 5 , startingFrom: 0 , length: 10 , options: [ . InsertionIndex, . LastEqual] )
129
+ XCTAssertTrue ( indexOfLeastGreaterObjectThanFive == 7 , " If both .InsertionIndex and .LastEqual are specified NSArray returns the index of the least greater object... " )
130
+
131
+ let endOfArray = objectIndexInArray ( array, value: 10 , startingFrom: 0 , length: 13 , options: [ . InsertionIndex, . LastEqual] )
132
+ XCTAssertTrue ( endOfArray == array. count, " ...or the index at the end of the array if the object is larger than all other elements. " )
133
+ }
134
+
135
+ func objectIndexInArray( array: NSArray , value: Int , startingFrom: Int , length: Int , options: NSBinarySearchingOptions = [ ] ) -> Int {
136
+ return array. indexOfObject ( NSNumber ( integer: value) , inSortedRange: NSRange ( location: startingFrom, length: length) , options: options, usingComparator: compareIntNSNumber)
137
+ }
138
+
139
+ func compareIntNSNumber( lhs: AnyObject , rhs: AnyObject ) -> NSComparisonResult {
140
+ let lhsInt = ( lhs as! NSNumber ) . integerValue
141
+ let rhsInt = ( rhs as! NSNumber ) . integerValue
142
+ if lhsInt == rhsInt {
143
+ return . OrderedSame
144
+ }
145
+ if lhsInt < rhsInt {
146
+ return . OrderedAscending
147
+ }
148
+
149
+ return . OrderedDescending
150
+ }
87
151
}
0 commit comments