zhuqh93
zhuqh93

Reputation: 63

Swift expression error (ambiguous without more context)

I'm new to Swift, currently practising some basic stuffs, when I try to figure out why dictionary content is not ordered, I found an answer from someone's post, the solution is add an index before it, like this:

[Int [String, String]]

when I tried to test it, there's an error about

expression type '[Dictionary<Int, Dictionary<String, Int>>]' is ambiguous without more context

no idea what went wrong, so I'll just show the code and look for help.

var animalNumbers = [[1: ["Cat": 1]], [2: ["Dog": 10]], [3: ["Aye-Aye": 98]]]

for (key, (animal, num)) in animalNumbers {
    print ("\(animal) = \(num)")
}

Upvotes: 6

Views: 607

Answers (3)

Rob
Rob

Reputation: 437452

I suspect you may have misunderstood that suggestion about the numeric key.

First, let's step back. I assume your original dictionary was as follows, and you were trying to solve the issue that the order wasn't preserved:

let animals = ["Cat": 1, "Dog": 10, "Aye-Aye": 98]

And I suspect you read that other answer and concluded that you needed to convert that to:

let animalNumbers = [[1: ["Cat": 1]], [2: ["Dog": 10]], [3: ["Aye-Aye": 98]]]

That's an array of nested dictionaries, with each dictionary having a numeric key. But that doesn't make sense. You're solving the problem twice. It's an ordered array of dictionaries, and the numeric key then also provides a mechanism for retrieving the values in some particular order. That's redundant.

The numeric key idea is to make that a dictionary whose key is a numeric value, and whose values are, themselves, dictionaries. If you were to do that, it's simpler than what you have there, but instead merely:

let animalNumbers = [0: ["Cat": 1], 1: ["Dog": 10], 2: ["Aye-Aye": 98]]

Note, that's a dictionary with numeric key, [Int: [String: Int]]. Anyway, once you have that dictionary, you can then theoretically do:

for i in 0 ..< animalNumbers.count {
    for (name, value) in animalNumbers[i]! {
        print(name, value)
    }
}

But, having reverse engineered what I suspect that other answer was suggesting, I should say that it's really not a very good pattern. If you want to insert values, you have to go through a nightmare of rebuilding all of those numeric keys.

Instead, just use a simple array of dictionaries, [[String: Int]], which is ordered, but eliminates many problems introduced with that manually constructed numeric key:

let animals = [["Cat": 1], ["Dog": 10], ["Aye-Aye": 98]]

Then you can:

for dictionary in animals {
    for (name, value) in dictionary {
        print(name, value)
    }
}

Finally, even better, you shouldn't be dealing with arrays of dictionaries, but rather an array of custom types:

struct Animal {
    let name: String
    let value: Int
}

let animals = [
    Animal(name: "Cat", value: 1),
    Animal(name: "Dog", value: 10),
    Animal(name: "Aye-Aye", value: 98)
]

Now that you're dealing with [Animal] type, you can just:

for animal in animals {
    print(animal.name, animal.value)
}

Upvotes: 2

vadian
vadian

Reputation: 285069

There are two issues:

  • The outer object is an array but the code uses dictionary enumeration syntax.
  • You can't enumerate nested objects in the same for loop.

The solution is to use a second for loop

let animalNumbers = [[1: ["Cat": 1]], [2: ["Dog": 10]], [3: ["Aye-Aye": 98]]]

for animal in animalNumbers {
   for (key, value) in animal {
        print ("\(key) = \(value)")
    }
}

And regarding why dictionary content is not ordered that's how a dictionary is defined :

A dictionary stores associations between keys of the same type and values of the same type in a collection with no defined ordering .

Upvotes: 0

Abhishek Jain
Abhishek Jain

Reputation: 4739

Do it like this-

var animalNumbers = [[1: ["Cat": 1]], [2: ["Dog": 10]], [3: ["Aye-Aye": 98]]]

        for animal in animalNumbers {
            for (animalName, num) in animal
            {
                print ("\(animalName) = \(num)")
            }
        }

Upvotes: 0

Related Questions