Swift: Array Find by Identity

How to find index of list item in Swift?

As swift is in some regards more functional than object-oriented (and Arrays are structs, not objects), use the function "find" to operate on the array, which returns an optional value, so be prepared to handle a nil value:

let arr:Array = ["a","b","c"]
find(arr, "c")! // 2
find(arr, "d") // nil

Use firstIndex and lastIndex - depending on whether you are looking for the first or last index of the item:

let arr = ["a","b","c","a"]

let indexOfA = arr.firstIndex(of: "a") // 0
let indexOfB = arr.lastIndex(of: "a") // 3

Swift arrays identity Type does not conform to protocol 'AnyObject' error

According to The Swift Programing Language:

”Identical to” [represented by three equals signs, or ===] means that two constants or variables of class type
refer to exactly the same class instance.

In Swift, Arrays are Structs. Therefore, you can't try to use === to compare one Array to another one. Otherwise, the following code - using NSArray - works fine and does not give any error message in Playground:

var a = [1, 2, 3] as NSArray //NSArray is not a Struct
var b = a
a === b //true

The explanation of this is given by The Swift Programing Language:

Structure instances are always passed by value, and  class instances
are always passed by reference.

Of course, Identical to (===) has not the same goal than Equal to (==) which helps you to check that two instances are considered “equal” or “equivalent” in value. For example, the following code will compile in Playground without any error message:

var a = [1, 2, 3]
var b = a
a == b //true

How to get an object index from an array in swift

Read the error message carefully

...not contained in a closure

By definition a closure is enclosed in a pair of curly braces

array.indexOf({$0 == observer})

or with trailing closure syntax

array.indexOf{$0 == observer}

Edit:

Since a protocol does not conform to Equatable by default use the identity operator

array.indexOf{$0 === observer}

Check if Swift array contains instance of object

Use the identity operator

static func ==(lhs: Car, rhs: Car) -> Bool {
return lhs === rhs
}

Or even without Equatable

myCars.contains{ $0 === mazda }

Edit: But a better solution is to implement equality rather than identity, for example a vendor and type property in the class

static func ==(lhs: Car, rhs: Car) -> Bool {
return lhs.vendor == rhs.vendor && lhs.type == rhs.type
}

Search for a value in two dimensional array

Here's a function which i implemented which checks if an element is listed within the multi-dimension array and returns the total elements found:

  • using .flatMap(_:) to flattened the multi-dimension arrays into one level.
  • using .filter(_:) to return the elements that are allowed based on the predicate.

    import UIKit

    var groups = [[String]]()

    // we create three simple string arrays for testing
    var groupA = ["England", "Ireland", "Scotland", "Wales"]
    var groupB = ["Canada", "Mexico", "United States"]
    var groupC = ["China", "Japan", "South Korea"]

    // then add them all to the "groups" array
    groups.append(groupA)
    groups.append(groupB)
    groups.append(groupC)

    func findElementInMultiDimension(element: String) -> Int {
    var count = 0
    let _ = groups.flatMap{$0.filter { (item) -> Bool in
    if item.contains(element) {
    count = count + 1
    return true
    } else {
    return false
    }
    }}
    return count
    }

    findElementInMultiDimension(element: "Mexico")
    print(findElementInMultiDimension(element: "Mexico")) //prints 1

Hope this helps :)

How to get index of an item in a array?

As Oliver pointed out, you can use

let index = array.indexOf(myObject)

However, this will only work if your object conforms to the Equatable protocol, to conform to it, you have to implement the == function, like this:

class MyClass {
}

extension MyClass: Equatable { }

func ==(lhs: MyClass, rhs: MyClass) -> Bool {
return lhs === rhs // === returns true when both references point to the same object
}

If your class inherits from NSObject and your comparison is something other than just comparing pointers, you'll have to override isEqual: as well

override func isEqual(object: AnyObject?) -> Bool {
guard let obj = object as? MyClass else { return false }
return self == obj
}

Find delegate in a swift Array of delegates

Update for Swift 4.2:

Assuming that the delegates are actually instances of a class, you could require that in the protocol by "inheriting" from "class":

protocol LocationManagerDelegate: class {
// ...
}

and then use the firstIndex(where:) method, using the "identity operator
===:

class LocationManager: NSObject {
private var _delegates = [LocationManagerDelegate]()

func removeDelegate(delegate:LocationManagerDelegate) {
if let index = _delegates.firstIndex(where: { $0 === delegate }) {
_delegates.remove(at: index)
}
}
}

Old answer (Swift 1):

There are two slightly different contains() functions:

func contains<S : SequenceType where S.Generator.Element : Equatable>(seq: S, x: S.Generator.Element) -> Bool

func contains<S : SequenceType, L : BooleanType>(seq: S, predicate: (S.Generator.Element) -> L) -> Bool

You are using the first one, which requires that the sequence elements conform to
the Equatable protocol, i.e. they can be compared with ==.

Assuming that the delegates are actually instances of a class, you could require
that in the protocol by "inheriting" from "class":

protocol LocationManagerDelegate : class {
// ...
}

and then use the second, predicate-based version of contains() with the
identity operator ===:

func removeDelegate(delegate:LocationManagerDelegate) {
if contains(_delegates, { $0 === delegate }) {
// Remove delegate
}
}

To remove the object from the array you'll have to get its index, so you might use
the findIdenticalObject() function from https://stackoverflow.com/a/25543084/1187415:

func findIdenticalObject<T : AnyObject>(array: [T], value: T) -> Int? {
for (index, elem) in enumerate(array) {
if elem === value {
return index
}
}
return nil
}

and then find and remove from the array with

func removeDelegate(delegate:LocationManagerDelegate) {
if let index = findIdenticalObject(_delegates, delegate) {
_delegates.removeAtIndex(index)
}
}

Sort array from CoreData Identity

You have first to fetch the data then sort them

self.fetchData()
userArray.sort { $0.naamdeelnemer! < $1.naamdeelnemer!}

However this is not CoreData like. Fetch the data passing a sort descriptor. This is much more efficient

func fetchData() {

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let request : NSFetchRequest<Punten> = Punten.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(key: "naamdeelnemer", ascending: true)]

do {
userArray = try context.fetch(request)
}
catch {
print(error)

}
}

and

userArray.sort { $0.naamdeelnemer! < $1.naamdeelnemer!}

Identify Duplicates In Array

Based on your comment I have made a simple example with string arrays, which can easily be converted to your movie type:

let movies = ["Batman","Batman","Flash","Avengers"]
var movieCounts:[String:Int] = [:]
for movie in movies {
movieCounts[movie] = (movieCounts[movie] ?? 0) + 1
}

And you can test it like so:

for (key, value) in movieCounts {
print("\(key) has been selected \(value) time/s")
}


Related Topics



Leave a reply



Submit