Taha Taha - 4 years ago 119
Swift Question

How to check if an object is in array

In swift, how can i check if an object is in array?

I have a simple class like this;

class Test: {
private var _number: Int!
private var _type: String!

var number: Int {
return _number
}
var type: String {
return _type
}

init (number: Int, type: String) {
self._number = number
self._type = type
}
}


Also i have this class;

class TestRandom {

private let _numberArr: [Int] = [1,2,3,4,5,6,7,8,9,10]
private let _typeArr: [String] = ["x","y","z"]
public private(set) var _testArr: [Test] = []
private var _randomTest: Test!

func randomTestPicker () {
repeat {

let randomNumber = Int(arc4random_uniform(UInt32(self._numberArr.count)))
let randomType = Int(arc4random_uniform(UInt32(self._typeArr.count)))

self._randomTest = Test(number: self._numberArr[randomNumber], type: self._typeArr[randomType])
} while self._testArr.contains(_randomTest)
}
}


All i want to do is to pick different objects. Lets say i have x2,y4,x6,z3,z8,y2 in _testArr. When i call randomTestPicker, it should not pick x2 or z8. Because they are already in array.

I have tried contains as you see. However it did not work for me. Is there any solution that i can use for this purpose? Or what is the best way to do this?

Edit: I tried
self._testArr.contains{$0 === _randomTest}
but not working neither.

Answer Source

You can't use contains that way since your class doesn't conform to the Equatable protocol.

Add :Equatable to your class definition and implement the == function which compares two of your objects:

class Test: Equatable {
    private var _number: Int!
    private var _type: String!

    var number: Int {
        return _number
    }
    var type: String {
        return _type
    }

    init (number: Int, type: String) {
        self._number = number
        self._type = type
    }
}

func ==(lhs: Test, rhs: Test) -> Bool {
    return lhs.number == rhs.number && lhs.type == rhs.type
}

The other way this could have been done is to use the predicate form of contains. The predicate takes two objects and returns a Bool indicating if they match. In that case, you would write:

self._testArr.contains { $0.number == _randomTest.number && $0.type == _randomTest.type }

As you can see, in this case the closure is essentially the == function from above, so implementing the Equatable protocol is the cleaner way to do it.

The closure { $0 === _randomTest } doesn't work because that only tests if the objects are the same instance. In your case, you need to check if the two objects have the same properties, and you are not interested if they are same instance. The way you are creating the objects, you never would create an instance that is already in the array, so this check would always return false.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download