Martin Koles
Martin Koles

Reputation: 5247

How to get index of enum case in array

I need to update associated value of Enum stored in an Array. How can I access the cell of the proper case without knowing its index?

enum MessageCell {
    case from(String)
    case to(String)
    case subject(String)
    case body(String)
}

var cells = [MessageCell.from(""), MessageCell.to(""), MessageCell.subject(""), MessageCell.body("")]

let recipient = "John"

// Hardcoded element position, avoid this
cells[1] = .to(recipient)

// How to find the index of .to case
if let index = cells.index(where: ({ ... }) {
    cells[index] = .to(recipient)
}

Upvotes: 4

Views: 4526

Answers (4)

Hamish
Hamish

Reputation: 80931

As an alternative to using index(where:), you could use pattern matching with a for loop instead in order to iterate over the indices of the elements that match the given case, then simply break on the first match:

var cells: [MessageCell] = [.from(""), .to(""), .subject(""), .to("")]

let recipient = "John"

for case let (offset, .to) in cells.enumerated() {
    cells[offset] = .to(recipient)
    break
}

print(cells) 
// [MessageCell.from(""), MessageCell.to("John"),
//  MessageCell.subject(""), MessageCell.to("")]

Upvotes: 4

vacawama
vacawama

Reputation: 154691

Use if case to test for the enum case .to in the closure and return true if found, otherwise return false:

if let index = cells.index(where: { if case .to = $0 { return true }; return false }) {
    cells[index] = .to(recipient)
}

Here's a complete example:

enum MessageCell {
    case from(String)
    case to(String)
    case subject(String)
    case body(String)
}

var cells: [MessageCell] = [.from(""), .to(""), .subject(""), .body("")]

if let index = cells.index(where: { if case .to = $0 { return true }; return false }) {
    print(".to found at index \(index)")
}

Output:

.to found at index 1

Upvotes: 14

Rashwan L
Rashwan L

Reputation: 38833

Here is a simplified demo of how you can solve this so that you get the idea of how this works:

var arr = ["a", "b"] // a, b
if let index = arr.index(where: { $0 == "a" }) {
    arr[index] = "c"
}
print(arr) // c, b

In your case:

if let index = cells.index(where: { if case .to = $0 { return true } else { return false } }) {
    cells[index] = .to(recipient)
}

Upvotes: 1

PGDev
PGDev

Reputation: 24341

Try this:

if let index = cells.index(where: { (messageCell) -> Bool in
            switch messageCell
            {
            case .to(let x):
                return x == recipient ? true : false
            default:
                return false
            }
        })
        {
            cells[index] = .to(recipient)
        }

Upvotes: 0

Related Questions