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

+3


source to share


1 answer


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]!)")
    }
}

      

+7


source







All Articles