0

I set up an array like this:

let modelArray = [
    "Casual":   ["health": 17, "weapon": 8, "crafting": 15, "social": 30],
    "Soldier":  ["health": 25, "weapon": 32, "crafting": 8, "social": 5],
    "Doctor":   ["health": 35, "weapon": 5, "crafting": 15, "social": 15],
    "Dorothy":  ["health": 15, "weapon": 15, "crafting": 20, "social": 20],
    "Asian":    ["health": 13, "weapon": 5, "crafting": 7, "social": 45],
    "Police":   ["health": 23, "weapon": 22, "crafting": 5, "social": 20]
]

How do I access the String (for example "Casual") value when looping?

for (index, model) in character.modelArray.enumerate()
{
    print("\(index) carries: \(model[0]")
}

This gives me Type '(String, Dictionary)' has no subscript members

2
  • 1
    That's not an array; it's a dictionary. Commented Aug 6, 2016 at 17:03
  • 1
    model is of type Dictionary<String, Dictionary<String, Int>> Commented Aug 6, 2016 at 17:17

2 Answers 2

3

As Josh points out, your modelArray object is a dictionary of dictionaries. (let modelArray : [String: [String:Int]] is the full type information).

The dictionary within can't be subscripted using an Int, only a String.

Here's a version of your code, which will get some the health stat of each character:

for statDictionary in characters.modelArray {
    let health = statDictionary["health"]
    print(health)
}

further suggestion

Storing data like this in a dictionary is fine for some purposes, but you may find a cleaner, safer API can be made by creating structs (or classes) for holding this state information.

struct CharacterStats {
     let health : Int
     let weaponNumber : Int
    // etc.
}

Then enumerating would be even simpler and require no loose string keys (which could be mistyped).

 for stat in characters {
     let health = stat.health
}
Sign up to request clarification or add additional context in comments.

2 Comments

Your answer did help the OP. But your first sentence is not correct. His modelArray is a dictionary of dictionaries and not an array. That makes it's definition to look like this: let modelArray : [String: [String:Int]].
Huh, I had it correct before, and for some reason I changed it to an incorrect definition today. Don't know what got into me. Thanks for catching my mistake, I reverted back to my original answer (which includes the accurate type information).
2

Just my point of view.

A dictionary of dictionaries is ugly

Create a model type

struct Model {
    let name: String
    let health: Int
    let weapon: Int
    let crafting: Int
    let social: Int
}

and then your array

let models = [
    Model(name: "Casual", health: 17, weapon: 8, crafting: 15, social: 30),
    Model(name: "Soldier", health: 25, weapon: 32, crafting: 8, social: 5),
    Model(name: "Doctor", health: 35, weapon: 5, crafting: 15, social: 15),
    Model(name: "Dorothy", health: 15, weapon: 15, crafting: 20, social: 20),
    Model(name: "Asian", health: 13, weapon: 5, crafting: 7, social: 45),
    Model(name: "Police", health: 23, weapon: 22, crafting: 5, social: 20),
]

Looping

Now you can simply

for model in models {
    print(model.name)
}

Update: Searching

if let doctor = models.filter({ $0.name == "Doctor" }).first {
    print(doctor.health)
}

1 Comment

I agree, it is indeed ugly. Will change it up like this instead. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.