I have a Dictionary that holds another Dictionary that holds an Array which holds another Array of a custom class. I'm having a lot of trouble working with these can someone who this comes easy to tell me the ways I can define, initialize, and access and assign to either part specifically.
Dic = [String: [String: [[MyClass]]]]
Sorry if it's confusing.
This code shows you how to do what you asked, but the data structure you requested is quiet cumbersome to use. I'll recommend to think again about what you want to accomplish and review this data structure.
class MyClass {
var name : String
init(name: String) {
self.name = name
}
}
// Create your dictionary
var dic : [String: [String: [[MyClass]]]] = [:]
// Create a list of MyClass object
var list = [MyClass(name: "first"), MyClass(name: "second"), MyClass(name: "third")]
// Create a dictionary with string key and array of array of type MyList
var myClassDic = ["test": [list]]
// update or add new value via the updateValue method
dic.updateValue(myClassDic, forKey: "index1")
// update or add new value via the subscript
dic["index2"] = ["test2": [[MyClass(name: "forth"), MyClass(name: "fith")]]]
// Iterate over your outer dictionairy
for key in dic.keys {
// retrieve an entry from your outer dictionary
var tempDic = dic[key]
// Iterate over your inner dictionary
for sKey in tempDic!.keys {
// retrieve an array of array of MyList Object
var containerList = tempDic![sKey]
// iterate over the outer array
for listVal in containerList! {
//Iterate over the inner array
for sListVal in listVal {
print("\(sListVal.name) ")
}
println()
}
}
}
Related
lets say you have the classes:
class Artwork {
var title = ""
var location =""
var author = ""
}
class GroupedArtworks {
var location = ""
var artworks = [Artworks]()
}
then you have an variable that contains several objects of the class "Artwork":
var arts = [artwork1, artwork2...]
How would I group the objects of the class "Artwork" by "location"?
I would like to end up with another variable containing objects of the class "GroupedArtworks"
and for each object, in the attribute "artworks" have all the objects that have the same "location"
so something like:
var orderedArtworks = [groupedartworks1, groupedartworks2...]
No doubt for loops are involved here.
The solution is super easy with Swift's Dictionary init(grouping:by:)
let artworks: [Artwork] = []
// dictionary type will be [String: [Artwork]]
let dictionary = Dictionary(grouping: artworks, by: \.location)
// now we can easy iterate over (key: String, value: [Artwork]) pairs
let groups: [GroupedArtworks] = dictionary.map { location, artworks in
GroupedArtworks(location: location, artworks: artworks)
}
// or simply
let groups = dictionary.map(GroupedArtworks.init)
// Swift will infer the types of dictionary and the init
but you will need to add this init to your GroupedArtworks
class GroupedArtworks {
let location: String
let artworks: [Artwork]
init(location: String, artworks: [Artwork]) {
self.location = location
self.artworks = artworks
}
}
Documentation
As someone correctly pointed out in the comments, since dicts are unordered collections, your array of GroupedArtworks will be unordered one as-well. But this should not be a problem since you can easily sort it by lets say location.
let groups = dictionary.map(GroupedArtworks.init).sorted(by: \.location)
I have an dictionary and the value containts the array of string as follows
arr = ["key":"["a","b","c","d","e","f","g"]"]
I want the new array to be like
let array = ["a","b","c","d","e","f","g"]
How to parse it
You can access dictionary items in few different ways, the easiest is:
let array = arr["key"]
You may need to conditionally unwrap it
if let array = arr["key"] as? [String] {
// rest of code with array
}
I've created a custom class to hold image and its string(its name)
class Countries: NSObject {
var countryName : String
var countryFlag : UIImage
init(countryName: String, countryFlag: UIImage) {
self.countryName = countryName
self.countryFlag = countryFlag
super.init()
}
}
I declared the class
var myList: Array<Countries> = []
And add each country info to the array
let image = UIImage(data:imageData!)
let dd = Countries(countryName: object["CountryName"] as! String, countryFlag: image!)
self.myList.append(dd)
I tried below code to sort the array but doesn't work;
self.myList.sortInPlace({ $0.countryName < $1.countryName })
Does anybody has idea how can I sort my array according to above code?
You can sort an array like this using -sortUsingComparator:, which you pass a block into. The block takes the two objects you want to compare and returns a NSComparisonResult which is your comparison of the two. You could provide a block that uses countryName.
You could alternatively use -sortUsingDescriptors: and pass in a NSSortDescriptor that looks at the countryName field.
I currently have a dictionary that contains 1 value per key. Is it possible to have 2 values per key?
var data = HomeVC.getData()
MyVariables.users = data.users;
MyVariables.img = data.img;
//MY Current dictionary with 1 value and 1 key
for (index, element) in enumerate(MyVariables.users)
{
MyVariables.dictionary[element as! String] = MyVariables.img[index]
}
I'm trying to add values from another array to this dictionary. So in total I would have 3 arrays in the same index position when calling them. 2 values and 1 key
You can use arrays or tuples as values of a dictionary:
var dictionary: Dictionary<String, (ValType1, ValType2)>
dictionary["foo"] = (bar, baz)
println(dictionary["foo"][1])
Instead of that try saving an NSArray as the value for key. The NSArray will be able to save more than 1 values and should suffice.
The lifecycle for a 2 values per key would look something like this
myDict[#"key1"] = value1;
// then set next value
myDict[#"key1"] = value2;
Now your dictionary has lost the first value and you only have access to the last one.
Your code would look something like
for (index, element) in enumerate(MyVariables.users)
{
var savedArray: [Your-Object-Type-Here]? = []
var savedArray = MyVariables.dictionary[element as! String]
if savedArray != nil {
savedArray!.append(MyVariables.img[index])
}
else {
savedArray = []
}
MyVariables.dictionary[element as! String] = savedArray
}
If your values are different types, create a custom class to hold the values. Make your dictionary keys point to objects of your custom class.
I have two separate arrays that I want to import into a dictionary. Order is extremely important because both arrays must match in index
struct MyVariables {
static var users:NSArray!
static var img:NSArray!
}
var data = SearchVC.getData()
MyVariables.users = data.users; //array 1 (key)
MyVariables.img = data.img; //array 2
// Goal is to insert these arrays into a dictionary while maintaing the matching indexes on both arrays
// Dictonary (MyVariables.img, key: MyVariables.users)
A Dictionary does not have a particular order. However, if both arrays have the same length, it is quite easy to iterate over them together:
var dictionary = [NSString: AnyObject]()
for var index = 0; index < data.users.count; index++ {
let img = data.img as! NSString
dictionary[img] = data.users[index]
}
Or, as #robertvojta suggested, use the zip() method:
var dictionary = [NSString: AnyObject]()
for (user, image) in zip(data.users, data.img) {
let img = image as! NSString
dictionary[img] = user
}
The key in a dictionary in swift must be hashable. i.e., not AnyObject.
Assuming you can replace some of your untyped Swift arrays, or cast them like so:
struct MyVariables {
var users:Array<AnyObject>
var img:Array<String>
}
then you can iterate through 1 array using a preferred Swift method and access the second using indexing:
var dictionary = Dictionary<String, AnyObject>()
for (index, element) in enumerate(MyVariables.img) {
dictionary[element] = MyVariables.users[index]
}
Use for loop for travels the array in that as per index access keys and values respective array and add it in dictionary. Its so simple so you can achive your goal using it.
I hope it will help you!