2

I have an array of Zombies, each Zombie is a struct as follows:

struct Zombie {
    var number: Int
    var location : Int
    var health : Int
    var uid : String
    var group: Int
}

I have an array of Zombies

ZombieArray = [Zombie1, Zombie2, Zombie3]

I have to update the zombieHealth when it changes, but I need to find which Zombie it is first. Each zombie's Location, Number, and UID is unique, so any of those can be searched. Here's what I tried and got an error:

let zombieToUpdate : Zombie?

for zombieToUpdate in self.zombieArray {
    if zombieToUpdate.location == thisZombieLocation {
        let indexOfUpdateZombie = zombieArray.indexOf(zombieToUpdate)
        self.zombieArray.remove(at: indexOfUpdateZombie)
        self.zombieArray.append(thisNewZombie)
    }
}

I'm getting the following error:

Cannot convert value of type 'Zombie' to expected argument type '(Zombie) throws -> Bool'

This error occurs on line:

let indexOfUpdateZombie = zombieArray.indexOf(zombieToUpdate)
nathan
  • 9,329
  • 4
  • 37
  • 51
Mason Ballowe
  • 1,847
  • 2
  • 12
  • 23
  • In Swift 3, it would be `index(of:)`, not `indexOf()`. – rmaddy Aug 13 '17 at 21:11
  • I tried that and got the following: Cannot invoke 'index' with an argument list of type '(of: Zombie)' – Mason Ballowe Aug 13 '17 at 21:12
  • Make your type Equatable, or use `index(where: predicate)` ... See https://stackoverflow.com/questions/24028860/how-to-find-index-of-list-item-in-swift – Martin R Aug 13 '17 at 21:14
  • 1
    You need to make `Zombie` conform to the `Equatable` protocol to use `index(of:)`. If you don't want to do that, use `index(where:)` or get the index as part of your iteration. – rmaddy Aug 13 '17 at 21:14
  • as in: let indexOfUpdateZombie = self.zombieArray.index(where: zombieToUpdate.location = thisZombieLocation) ?? Won't run – Mason Ballowe Aug 13 '17 at 21:18
  • What exactly are you trying to achieve here? Each `index(of:)` is doing a full search through the array. You're already iterating the array in a `for` loop, so why not just keep track of the index yourself using `.enumerated()`? – Alexander Aug 13 '17 at 21:26

1 Answers1

2

Since Zombie doesn't conform to Equatable, you can't use index(of:).

If you don't want to add that functionality, you have a couple of choices for implementing your logic.

Option 1 - Use index(where:):

if let index = zombieArray.index(where: { $0.location == thisZombieLocation }) {
    zombieArray.remove(at: index)
    zombieArray.append(thisNewZombie)
}

No need for the loop.

Option 2 - Iterate with an index:

for index in 0..<zombieArray.count {
    let zombieToUpdate = zombieArray[index]
    if zombieToUpdate.location == thisZombieLocation {
        zombieArray.remove(at: index)
        zombieArray.append(thisNewZombie)
        break // no need to look at any others
    }
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579