Swift: associative array with multiple keys: values
I'm not an expert in Swift and I've been using it for months to build Mac Apps. I would like to represent in memory a data structure similar to that of PHP's associative arrays , but in Swift . Imagine I have a data table to load into memory with the following fields / records:
ID Surname Name
1 XXX YYY
2 ZZZ WWW
3 JJJ KKK
What I would like to get is an associative array, similar to what I could get in PHP:
$arr[1]["Surname"] = "XXX"
$arr[1]["Name"] = "YYY"
$arr[2]["Surname"] = "ZZZ"
$arr[2]["Name"] = "WWW"
I just can't seem to find the data structure I need in Swift to get the same result. I've tried using the following piece of code:
class resObject: NSObject {
private var cvs = [Int: [String: String]]()
override init() {
self.cvs[0] = ["Name" : "XXX"]
self.cvs[0] = ["Surname" : "YYY"]
self.cvs[1] = ["Name" : "ZZZ"]
self.cvs[1] = ["Surname" : "WWW"]
for (key, arr) in cvs {
let sur = arr["Surname"]
let nam = arr["Name"]
println("Row \(key) - Surname: \(sur), Name: \(nam)")
}
super.init()
}
}
It looks pretty close, but it doesn't work. What I get in the output is the following (I don't need the "Optional (s)":
Row 0 - Surname: Optional("XXX"), Name: nil
Row 1 - Surname: Optional("ZZZ"), Name: nil
I tried to run some tests in debug and I noticed that the data that is stored in memory is only the one used for the last key pair: value (i.e. if I assign the last name and first name to the second one, I get the last name as nil and Name with the correct value).
Please note that, as in the example, I don't know the data structure when I declare the variable, so I declare it empty and fill it in programmatically later.
I don't know if I am declaring the data structure correctly, or if it is Swift that does not allow this. Any help would be greatly appreciated.
Many thanks. Regards, Alessio
source to share
One of the ways is Dictionary
of structs
. Consider:
struct Person {
var firstName: String
var lastName: String
}
var peopleByID = [ Int: Person ]()
peopleByID[1] = Person(firstName: "First", lastName: "Last")
peopleByID[27] = Person(firstName: "Another", lastName: "LastName")
var myID = 1 // Try changing this to 2 later
if let p = peopleByID[myID] {
println("Found: \(p.firstName) with ID: \(myID)")
}
else {
println("No one found with ID: \(myID)")
}
Then you can update the structure:
peopleByID[1].firstName = "XXX"
peopleByID[27].lastName = "ZZZ"
You can iterate freely:
for p in peopleByID.keys {
println("Key: \(p) value: \(peopleByID[p]!.firstName)")
}
Note that the simple array [Person] is not that hot because the identifiers are:
- there cannot be Intas, but are often strings
- even if they remain Ints, the array takes up storage in proportion to the index with the highest number, whereas the dictionary only takes up memory in proportion to the number of objects stored. Imagine you only store two IDs: 523123 and 2467411.
EDIT
It looks like you don't know in advance the attributes that will go into each Person
object. It's weird, but you have to do the following:
struct Person {
var attributes = [String : String]() // A dictionary of String keys and String values
}
var peopleByID = [ Int : Person ]()
// and then:
var p1 = Person()
var p2 = Person()
p1.attributes["Surname"] = "Somename"
p1.attributes["Name"] = "Firstname"
p2.attributes["Address"] = "123 Main St."
peopleByID[1] = p1
peopleByID[2] = p2
if let person1 = peopleByID[1] {
println(person1.attributes["Surname"]!)
for attrKey in person1.attributes.keys {
println("Key: \(attrKey) value: \(person1.attributes[attrKey]!)")
}
}
source to share