How to use indexesOfObjectsPassingTest: in Swift - ios

The declaration of indexesOfObjectsPassingTest: looks like this in Swift,
func indexesOfObjectsPassingTest(predicate: ((AnyObject!, Int, CMutablePointer<ObjCBool>) -> Bool)!) -> NSIndexSet!
I've tried all sorts of permutations to get this to work, but I'm stumped, particularly with how you deal with this piece, CMutablePointer<ObjCBool>) -> Bool)!. I found it confusing enough, when I was first learning blocks in objective-c, how you translate from the declaration to actual use of a method, and the syntax of Swift is at least as confusing.

This code is working in the Playground for me ;) Hope it helps a bit
Extra Function-Definition
import Cocoa
let list = [2, 3, 4, 5, 6, 7, 8]
func test (object: AnyObject!, index: Int, stop: CMutablePointer<ObjCBool>) -> Bool
{
let number = object as Int
return (number % 2 == 0) //for even numbers
}
let result: NSIndexSet = (list as NSArray).indexesOfObjectsPassingTest(test)
println("\(result.lastIndex)") //prints "6" (because 8%2=0)
Inline-Closure
I transformed my above example to work with an inline-closure (described in the Swift-eBook). The parameter-list and return-type is separated by the term in.
import Cocoa
let list = [2, 3, 4, 5, 6, 7, 8]
let result: NSIndexSet = (list as NSArray).indexesOfObjectsPassingTest({
(object: AnyObject!, index: Int, stop: CMutablePointer<ObjCBool>) -> Bool in
let number = object as Int
return (number % 2 == 0) //for even numbers
})
println("\(result.lastIndex)") //prints "6" (because 8%2=0)

Seems like CMutablePointer was recently changed to UnsafeMutablePointer.
This one worked for me:
let indices = myArray.indexesOfObjectsPassingTest({
(obj: AnyObject!, idx: Int, stop: UnsafeMutablePointer<ObjCBool>) -> Bool in
var didPass = false
//determine if obj passes test, if it does set didPass = true
return didPass
})

The block syntax is being replaced in Swift by a closure, the predicate parameter here.
So you can just do:
var array = NSArray(array: [1, 2, 3, 4, 5])
var indexSet = array.indexesOfObjectsPassingTest({ (val: AnyObject!, index: Int, stop: CMutablePointer<ObjCBool>) -> Bool in return index > 2 })
indexSet.count
Out of the method, it could look like this:
var closure = {(val: AnyObject!, index: Int, stop: CMutablePointer<ObjCBool>) -> Bool? in
/* Do Something */
}
Hope this helps.

Related

Find lowest value and its index number in swift

I have the following array
var numbers = [2, 4, 4, 2, 3, 1]
The sequence is very important and I need to find the index of the lowest value.
So how can I find the lowest value index? I need to be able to call numbers[lowestValueIndex] and get the correct value
Any help is appreciated
I always think it gives a cleaner call site to extend the array in this type of scenario.
extension Array where Element == Int {
func lowest() -> (value: Element, positions:[Index])? {
guard !isEmpty else {return nil } //you may wish to throw an error rather than return nil
return indices.reduce( (value: Element.max, positions: [Index]() ) ) {
switch self[$1] {
case let x where x < $0.value: return (value: self[$1], positions:[$1])
case let x where x > $0.value: return $0
default: return ($0.value, $0.positions + [$1])
}
}
}
}
The switch statements can be simplified using an _ or pattern matching, but I feel this more verbose approach is easier to understand. Throwing an error or returning a Result may be nicer way of dealing with an empty array than an optional return type, but would add bloat to the answer and can be added later by the OP if preferred.
[2,3,6,1,7,3,1,6,7].lowest() // (value: 1, positions: [3, 6])
[2,3,6,6,7,3,1,6,7].lowest() // (value: 1, positions: [6])
[Int]().lowest() // nil
You can use the min(by:) array method; The trick is to operate on the array's indices property so that you can return the relevant index:
func minIndex(someArray: [Int]) -> Int? {
return someArray.indices.min { someArray[$0] < someArray[$1] }
}
The function will return nil in the case where the array is empty.
For simplicity I have shown this as a function. You could, of course, implement this as an extension on Array if you desired.
The other answers handle what to do if you only need one value. Otherwise…
let numbers = [2, 4, 4, 2, 3, 1, 1]
// [(offset 5, element 1), (offset 6, element 1)]
numbers.min().map { min in
numbers.enumerated().filter { $0.element == min }
}
And if you're going to need the array sorted for further usage, prefix is better than filter.
let sorted =
[2, 4, 4, 2, 3, 1, 1]
.enumerated()
.sorted(by: \.element)
sorted.first.map { first in
sorted.prefix { $0.element == first.element }
}
public extension Sequence {
/// Sorted by a common `Comparable` value.
func sorted<Comparable: Swift.Comparable>(
by comparable: (Element) throws -> Comparable
) rethrows -> [Element] {
try sorted(by: comparable, <)
}
/// Sorted by a common `Comparable` value, and sorting closure.
func sorted<Comparable: Swift.Comparable>(
by comparable: (Element) throws -> Comparable,
_ areInIncreasingOrder: (Comparable, Comparable) throws -> Bool
) rethrows -> [Element] {
try sorted {
try areInIncreasingOrder(comparable($0), comparable($1))
}
}
}
First you need to define the behavior of repetitive value in the input array.
Once that is done, try this:
func returnLowestValueIndex(array: [Int]) -> Int? {
guard !array.isEmpty else { return nil }
var lowestValueIndex: Int = 0
for (index, value) in array.enumerated() {
if value < array[lowestValueIndex] {
lowestValueIndex = index
}
return lowestValueIndex
}
var numbers = [2, 4, 4, 2, 3, 10]
returnLowestValueIndex(array: numbers)

Using higher order functions in swift

I am learning swift coming from a Haskell background, I would like to translate this bit into swift:
match :: Int -> Bool
match = (>) 3
hasMatch :: (Int -> Bool) -> [Int] -> [Int]
hasMatch pred ns = filter pred ns
hasMatch match [1..5] = [4,5]
Silly example I know. This is what I have with swift:
func hasMatch(pred : (Int) -> Bool, ns : [Int]) -> [Int]{
return ns.filter{n in pred(n:n)}
}
func match(n: Int) -> Bool{
return n > 3
}
let os = hasMatch(pred : match, ns: [1,2,3,4,5])
Which does not compile. This is the error message:
let os = hasMatch(pred : match, ns: [1,2,3,4,5])
./hello-swift.swift:48:28: error: extraneous argument label 'n:' in call
return ns.filter{n in pred(n:n)}
^~~
./hello-swift.swift:48:24: error: closure use of non-escaping parameter 'pred' may allow it to escape
return ns.filter{n in pred(n:n)}
^
./hello-swift.swift:47:15: note: parameter 'pred' is implicitly non-escaping
func hasMatch(pred : (Int) -> Bool, ns : [Int]) -> [Int]{
^
#escaping
I have two questions:
I have pred(n:n) but this assumes that pred names its input as n, which does not make sense. Do all functions have to have named inputs?
How would I change to the code so that it compiles
func hasMatch(pred: (Int) -> Bool, ns: [Int]) -> [Int] {
return ns.filter { n in pred(n) }
}
You don't need parameter names if the function is a closure.
#escaping is a keyword in swift which tells the compiler that the passed in function will escape the current scope, so it needs to retain/release the passed in arguments (Swift, like objective-c, uses retain counting for memory management)
However, you don't need it in this case - that error was a red herring thrown by the compiler because it couldn't compile the line with filter in, so it didn't know whether you needed to escape or not. Looks like it plays things safe :)
As soon as you remove the n: and it can work out which filter you are calling, it knows that because filter doesn't need an #escaping closure, your method doesn't either so that error goes away.
func mapedData(){
let bookData = ["book1":120, "book2": 150]
let mapedData = bookData.map({(key,value) in return value + 40 })
print(mapedData)
}
// [160, 190]
func filterData()
{
let bookData = ["book1":127, "book2": 150 ,"book3": 289 ,"book4": 190, "book5": 950 ]
let filterData = bookData.filter({(key,value) in return value < 200})
print(filterData)
}
// ["book2": 150, "book4": 190, "book1": 127]
func reducedData()
{
let data = [1,2,3,4,5,6,7,8,9,10]
let reducedData = data.reduce(0, { sum , number in return sum + number })
print(reducedData)
}
//55
func compactData(){
let data = [1,nil,3,4,5,6,7,nil,9,10]
let cMap = data.compactMap({return $0})
print(cMap)
}
// [1, 3, 4, 5, 6, 7, 9, 10]
func flatMappedData(){
let data = ["sachin"]
let characters = data.flatMap({return $0})
print(characters)
}
// ["s", "a", "c", "h", "i", "n"]

Swift Array diff

Given two arrays, where one is the old set of values and the other is the new values, I want to find the "diff" of those two arrays such updates to the original array can be represented as:
enum CollectionChange<T: SequenceType> {
case Initial(T)
case Update(T, deletions: [Int], insertions: [Int], modifications: [Int])
}
I'm trying to build a simpler version of this where the changes object is built based on object equality, instead of indexes as RAC-MutableCollectionProperty is (for which the code is here and what might be the most complicated bit of code I've seen in a while; no documentation doesn't help).
Also important for this project is the ability to be able to observe changes to an array at any level of granularity. For example, a one-dimensional array, restricting T to Equatable, is a relatively easy use case. You can, as RAC-MutableCollectionProperty build up some sort of table that describes the changes, checking for equality on the objects. However once you get down to using two-dimensional arrays and deeper it gets a bit trickier because not only do you have to diff the elements at the lowest level but also describe section-level removals. In practice, no more than 2D arrays is really ever necessary but it'd be nice to have a solution that works regardless of the array depth. I'm not necessarily looking for a solution (although that'd be fantastic), really just any pointers and high level solutions on how to approach this problem.
One way I've thought of to observe multiple array levels is to write a diffing function that works on single dimensional arrays and construct a property such that:
let property: MutableCollectionProperty<MutableCollectionProperty<Int>>
where the property would check if its generic type is of it's own type. I'd have to change the changes description to something closer to
enum Changes<T> {
case Initial(T)
case Update(T, deletions: [NSIndexPath], insertions: [NSIndexPath], modifications: [NSIndexPath])
}
or maybe something like
enum Changes<T> {
case Initial(T)
case UpdateSections(sections: [T], deletions:[Int], insertions: [Int], modifications: [Int])
case UpdateIndexes(T, deletions: [Int], insertions: [Int], modifications: [Int])
}
These are just my preliminary thoughts though, I'm open to any solution or suggestion.
BOUNTY EDIT:
The bounty will be awarded to someone who can provide a solution that given the following parameters:
Let x and y be two swift array
both arrays of type T: Equatable
both arrays can be of any depth
the depth of x == the depth of y
a change set can be generated where a change set describes:
which elements have been deleted from the x
to y (by index)
which elements have been inserted into y that
weren't in x (by index)
which elements have been moved going from x
to y (by index)
Changes only have to be described at the lowest level of the array (no need to worry about insertion & removal of higher segments, although you'd really earn the 300 rep with that) but change indexes must indicate the nested index path.
For example, if the array is a 3d array and an object at array[0][5][2] was deleted, the resulting index change should be an array [0, 5, 2]. That array describes a single deletion and all the deletions would be of type [[Int]].
Edit:
I'm removing the requirement of the arrays being of any depth. Let's say that they're simply 1d arrays.
I'm not sure this meets all your bounty requirements, but I'll post some code I use for computing arrays differences:
func arrayInsertionDeletionAndNoopIndexes<T: Equatable>(objects: [T], originalObjects: [T]) -> ([Int], [Int], [Int]) {
let insertions = objects.filter({ !originalObjects.contains($0) }).map({ objects.index(of: $0)! })
let noops = originalObjects.filter({ objects.contains($0) }).map({ originalObjects.index(of: $0)! })
let deletions = originalObjects.filter({ !objects.contains($0) }).map({ originalObjects.index(of: $0)! })
return (insertions, deletions, noops)
}
func arrayInsertionDeletionAndNoopIndexPaths<T: Equatable>(objects: [T], originalObjects: [T], section: Int = 0) -> ([IndexPath], [IndexPath], [IndexPath]) {
let (insertions, deletions, noops) = arrayInsertionDeletionAndNoopIndexes(objects: objects, originalObjects: originalObjects)
let insertionIndexPaths = insertions.map({ IndexPath(row: $0, section: section) })
let deletionIndexPaths = deletions.map({ IndexPath(row: $0, section: section) })
let noopIndexPaths = noops.map({ IndexPath(row: $0, section: section) })
return (insertionIndexPaths, deletionIndexPaths, noopIndexPaths)
}
My specific use case is for computing differences to update a UITableView, for which purpose I also have the following:
extension UITableView {
func insertAndDeleteCellsForObjects<T: Equatable>(objects: [T], originalObjects: [T], section: Int = 0) {
let (insertions, deletions, _) = arrayInsertionDeletionAndNoopIndexPaths(objects: objects, originalObjects: originalObjects, section: section)
if insertions.count > 0 || deletions.count > 0 {
beginUpdates()
insertRows(at: insertions, with: .automatic)
deleteRows(at: deletions, with: .automatic)
endUpdates()
}
}
}
As of Swift 2.2, this is impossible.
You give the following requirements:
both arrays of type T: Equatable
both arrays can be of any depth
But the ability to make a constrained extension conform to a new protocol is only planned for Swift 3.0, so right now you can't make extension Array where Element: Array<Equatable> conform to Equatable protocol. This means that only 1d arrays can be of of type T: Equatable.
EDIT:
Basically what you need to do is to write an algorithm that solves Longest common subsequence problem. For 1d arrays you can use Dwifft library which solves the problem in the following way:
public extension Array where Element: Equatable {
public func diff(other: [Element]) -> Diff<Element> {
let table = MemoizedSequenceComparison.buildTable(self, other, self.count, other.count)
return Array.diffFromIndices(table, self, other, self.count, other.count)
}
private static func diffFromIndices(table: [[Int]], _ x: [Element], _ y: [Element], _ i: Int, _ j: Int) -> Diff<Element> {
if i == 0 && j == 0 {
return Diff<Element>(results: [])
} else if i == 0 {
return diffFromIndices(table, x, y, i, j-1) + DiffStep.Insert(j-1, y[j-1])
} else if j == 0 {
return diffFromIndices(table, x, y, i - 1, j) + DiffStep.Delete(i-1, x[i-1])
} else if table[i][j] == table[i][j-1] {
return diffFromIndices(table, x, y, i, j-1) + DiffStep.Insert(j-1, y[j-1])
} else if table[i][j] == table[i-1][j] {
return diffFromIndices(table, x, y, i - 1, j) + DiffStep.Delete(i-1, x[i-1])
} else {
return diffFromIndices(table, x, y, i-1, j-1)
}
}
}
internal struct MemoizedSequenceComparison<T: Equatable> {
static func buildTable(x: [T], _ y: [T], _ n: Int, _ m: Int) -> [[Int]] {
var table = Array(count: n + 1, repeatedValue: Array(count: m + 1, repeatedValue: 0))
for i in 0...n {
for j in 0...m {
if (i == 0 || j == 0) {
table[i][j] = 0
}
else if x[i-1] == y[j-1] {
table[i][j] = table[i-1][j-1] + 1
} else {
table[i][j] = max(table[i-1][j], table[i][j-1])
}
}
}
return table
}
}
If you only need to compute the difference between two arrays, here's an alternative implementation based on shawkinaw answer:
typealias Insertions = [Int]
typealias Deletions = [Int]
typealias ChangeSet = (Insertions, Deletions)
func Diff<T: Equatable>(objects: [T], originalObjects: [T]) -> ChangeSet {
guard objects.count > 0 && originalObjects.count > 0 else { return ChangeSet([], []) }
let insertedObjects = objects.filter({ !originalObjects.contains($0) })
let insertionIndicies = insertedObjects.compactMap({ objects.index(of: $0) })
let deletedObjects = originalObjects.filter({ !objects.contains($0) })
let deletionIndicies = deletedObjects.compactMap({ originalObjects.index(of: $0) })
return ChangeSet(insertionIndicies, deletionIndicies)
}
The insertionIndicies is an array of type Int. Each Int in the array refers to the indicies where the originalObjects array need to insert items from the objects array.
The deletionIndicies is an array of type Int. Each Int in the array refers to the indicies where the originalObjects array has to delete items.

Use logical operator as combine closure in reduce

I am trying to reduce an array of Bools by applying the logical operator OR (||) using the following code, however I get an error:
func reduceBools(values: [Bool]) -> Bool {
return values.reduce(false, combine: ||)
}
Ambiguous reference to member '||'
Analogously for integers the code works like a charm.
func reduceInts(values: [Int]) -> Int {
return values.reduce(0, combine: +)
}
I was able to make it work by adding a || function (code below) or using a { $0 || $1 } closure but I dislike these approaches and I would prefer simply passing the operator.
func ||(lhs: Bool, rhs: Bool) -> Bool {
return lhs || rhs
}
The same thing happens for the logical AND (&&) operator.
How can I make it work without using the hack above?
As an alternative, you could use the following approach
// ||
func reduceBoolsOr(values: [Bool]) -> Bool {
return values.contains(true)
}
// &&
func reduceBoolsAnd(values: [Bool]) -> Bool {
return !values.contains(false)
}
Note that .reduce comes with an overhead. If the end result is the importance of your question (rather than enquiring above the unexpected behaviour of || and && operators in this context), then perhaps the pragmatic approach above can be of help, even if it doesn't really reduce the array, however producing the same result due to the simple nature of the boolean type.
Swift 4.2+ / Xcode 10.0+
In modern versions of Swift there is allSatisfy function, which checks all elements for satisfying some rule.
In OP's case:
values.allSatisfy { $0 }
UPD:
To make this work for OR, do
!values.allSatisfy{!$0}
Thanks to Andy Weinstein
Following approach will work
values.reduce(false) { $0 || $1 }
Ambiguous reference to member '||' means, that there are more than one possible candidates, from which compiler is not able to choose. In your case those are
public func ||<T : BooleanType, U : BooleanType>(lhs: T, #autoclosure rhs: () throws -> U) rethrows -> Bool
and
public func ||<T : BooleanType>(lhs: T, #autoclosure rhs: () throws -> Bool) rethrows -> Bool
probably your 'hack' using a { $0 || $1 } is the best solutions here.
This happens because of Swifts closure semantics. It takes your arguments and applies function to them, omitting argument names.
protocol Numeric {
...
public static func +(lhs: Self, rhs: Self) -> Self
...
}
In example with Ints, you would pass (Int, Int) into a closure, and + function in Numeric protocol expects exactly two ints to sum them.
Thats why code like below works just fine
[1, 2, 3, 4].reduce(0, +)
Because you just took 2 ints, and applied function, which takes just two ints.
If you write your own function, which would take just two argument, it would work as well.
func myOwnAwesomeFunc<T: Numeric>(a: T, b: T) -> T { in
return 1 // production ready
}
[1, 2, 3, 4].reduce(0, myOwnAwesomeFunc) // prints 1
Good so far. But why can't we write
[true, false, true].reduce(false, ||) // yields Cannot invoke 'reduce'
// with an argument list of type
// '(Bool, (Bool, #autoclosure () throws -> Bool) throws -> Bool)'
That's because this operator takes bool and a closure, which returns bool. Not bool, closure!
But if it is like this, why aren't we writing true || { false }() ?
Thats because of #autoclosure, which takes care of curly braces for us.
Main question, why is it implemented this way, so we can't use Swifts awesome short-hand closure syntax with booleans? Idk
Here's another approach, I modified the reduceBools function to take the operator as a parameter -
typealias LogicalOperator = ((Bool, #autoclosure () throws -> Bool) throws -> Bool)
func reduceBools(values: [Bool], combine: LogicalOperator) -> Bool {
var started: Bool = false
return values.reduce(into: true, { (result, value) in
result = started ? try! combine(result, value) : value // obviously up to you how you'd handle the try/catch
started = true
})
}
let bools = [true, false, false, true]
let result1 = self.reduceBools(values: bools, combine: ||)
print(result1) // prints true
let result2 = self.reduceBools(values: bools, combine: &&)
print(result2) // prints false
Or it could be more useful as an extension of Sequence -
extension Sequence where Element == Bool {
func reduce(_ combine: LogicalOperator) -> Bool {
var started: Bool = false
return self.reduce(into: true, { (result, value) in
result = started ? try! combine(result, value) : value
started = true
})
}
}
print(bools.reduce(||)) // prints true

How to Declare a Multidimensional Boolean array in Swift?

I've seen so many different examples on how to do this but none of them seem to show an answer that I really need. So I know how to declare a multidimensional array of type bool.
var foo:[[Bool]] = []
However I cannot figure out how to declare this of type 10 x 10. Every example I look up just appends to an empty set, so how do I initialize this variable to be a 10x10 where each spot is considered a boolean?
The other answers work, but you could use Swift generics, subscripting, and optionals to make a generically typed 2D array class:
class Array2D<T> {
let columns: Int
let rows: Int
var array: Array<T?>
init(columns: Int, rows: Int) {
self.columns = columns
self.rows = rows
array = Array<T?>(count:rows * columns, repeatedValue: nil)
}
subscript(column: Int, row: Int) -> T? {
get {
return array[(row * columns) + column]
}
set(newValue) {
array[(row * columns) + column] = newValue
}
}
}
(You could also make this a struct, declaring mutating.)
Usage:
var boolArray = Array2D<Bool>(columns: 10, rows: 10)
boolArray[4, 5] = true
let foo = boolArray[4, 5]
// foo is a Bool?, and needs to be unwrapped
You can also do it with this oneliner:
var foo = Array(repeating: Array(repeating: false, count: 10), count: 10)
For Swift 3.1:
var foo: [[Bool]] = Array(repeating: Array(repeating: false, count: 10), count: 10)
See Swift documentation
As a one-liner, you can initialize like this with computed values assigned:
var foo = (0..<10).map { _ in (0..<10).map { $0 % 2 == 0 } }
Or
var bar = (0..<10).map { a in (0..<10).map { b in (a + b) % 3 == 0 } }

Resources