iterating through dictionary in TableView - ios

this might be a common situation, but I was not able to figure out a way how to do it.
I have a dictionary with the stock amount for several items: dict = ["item1" : 2, "item2" : 5, "item3" : 10 ]
How can I now assign the keys and values to different labels in a tableView, using indexPath?
The logic I want to achieve:
cell.itemLabel.text = dict.[firstItemName]
cell.amountLabel.text = dict.[firstItemAmount]

A dictionary as data source can be annoying because a dictionary is unordered.
My suggestion is to map the dictionary to an array of a custom struct and sort the array by the keys
struct Model {
let name : String
let value: Int
}
let dict = ["item1" : 2, "item2" : 5, "item3" : 10 ]
let array = dict.map(Model.init).sorted{$0.name < $1.name}
Then in the table view you can write
cell.itemLabel.text = array[indexPath.row].name

You can use map function to get separate array of key and values
print(dict.map({$0.key}))
print(dict.map({$0. value}))
Try this:
cell.itemLabel.text = dict.map({$0.key})[indexPath.row]
cell.amountLabel.text = dict.map({$0.value})[indexPath.row]

Related

Filter dictionary of array objects

I am trying to filter my dictionary according to user input in UISearchController. I have following model and array of objects.
struct People {
var name: String
var id: Int
}
let first = People(name: "Atalay", id: 1)
let second = People(name: "Ahmet", id: 2)
let third = People(name: "Mehmet", id: 3)
let fourth = People(name: "Yusuf", id: 4)
let peoples: [People] = [first, second, third, fourth, fifth]
I put them into a dictionary to create section indexed table view with following code.
var dict: [String: [People]] = Dictionary(grouping: peoples, by: { (people) -> String in
return String(people.name.prefix(1))
})
Above code gives me a dictionary with first letter of People names. Now, I would like to filter my array according to user input. However, I tried following code for filtering but it is not working as I expected.
let filteredDict = (dict.filter { $0.1.contains { $0.name.lowercased().contains("ata") } })
It returns all "A" letter section indexes like ["A": People(name: "Atalay", id: 1), People(name: "Ahmet", id: 2)]
How can I achieve filter also my array inside dictionary?
If I'm not mistaken, you want your final dictionary to have all the keys and only the filtered array of items as the values. If that is right, reduce is the tool for that:
let filtered = dict.reduce(into: [String: [People]]()) {
$0[$1.key] = $1.value.filter { $0.name.lowercased().contains("ata") }
}
I decided it was simplest to get this right by using an old fashioned for loop and filter each group separately
var filtered = [String: [People]]()
for (k, v) in dict {
let result = v.filter {$0.name.lowercased().contains("ata")}
if result.count > 0 {
filtered[k] = result
}
}
Note that if you want to keep all the groups in the result dictionary just skip the if result.count > 0 condition
How can I achieve filter also my array inside dictionary?
You should have an array first, you can use flatMap to group all the values in your filteredDict
let array = filteredDict.flatMap { $0.value }
Then you just filter the array as usually
let filteredArray = array.filter { $0.name.lowercased().contains("ata") }

Sorting array of dictionaries by value after for loop?

I've seen a lot of answers to similar questions but none of the methods have worked so far.
if let users = snapshot.value!["users"] as? Dictionary<String,AnyObject> {
each.users = Int(users.count)
var pointsArray = [Dictionary<String,Int>]()
for (key, value) in users {
let uid = key
let points = value["points"] as! Int
pointsArray.append([uid : points])
}
I'm then needing to sort pointsArray by the "points", sort it from high to low, grab the 0th (highest) element, then grab the uid to use.
I've tried:
var myArr = Array(pointsArray.keys)
var sortedKeys = sort(myArr) {
var obj1 = dict[$0] // get ob associated w/ key 1
var obj2 = dict[$1] // get ob associated w/ key 2
return obj1 > obj2
}
This gives me
Value of type [ Dictionary <String,Int>] has no member keys.
I guess that's cause I'm trying to run the sort on my array of dicts vs the dicts themselves? How do I switch this up to get into the actual dictionaries vs. running the sort on the array?
Right - you're not properly accessing the keys of the dictionaries.
Here's a working code:
var pointsArray = [Dictionary<String, Int>]()
pointsArray.append(["1" : 10])
pointsArray.append(["2" : 45])
pointsArray.append(["3" : 30])
// sort by points
let sorted = pointsArray.sort({ $0.first!.1 > $1.first!.1 })
print(sorted) // [["2": 45], ["3": 30], ["1": 10]]
Array(pointsArray.keys) - this doesn't work, because pointsArray is an array, therefore it doesn't have keys property. The contents of pointsArray are dictionaries and they have keys. So you can access the keys of the first dictionary like this: pointsArray[0].keys

Generate Sorted Dictionary by Letters from an Array Swift

I have an Array of Departments' Names
var departments: Array<String>!
I want to sort this array alphabetically in Dictionary e.g the dictionary should be like this
var MyDictionary = ["A": ["Affenpoo", "Affenpug", "Affenshire", "Affenwich", "Afghan Collie", "Afghan Hound"], "B": ["Bagle Hound", "Boxer"],
"C": ["Cagle Cound", "Coxer"]]
the departments array is not static
how can i generate this dictionary in swift?
Thanks a lot
My approach would be to iterate the array and take the first letter of each entry. Retrieve the array from the dictionary for that letter. If it is nil create a new array. Add the word to the array you retrieved and then store the array in the dictionary.
let departments = ["Affenpoo", "Affenpug", "Affenshire", "Affenwich", "Afghan Collie","Cagle Cound", "Coxer"]
var outputDict=[String:[String]]()
for word in departments {
let initialLetter=word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString
var letterArray=outputDict[initialLetter] ?? [String]()
letterArray.append(word)
outputDict[initialLetter]=letterArray
}
print(outputDict)
["C": ["Cagle Cound", "Coxer"], "A": ["Affenpoo", "Affenpug", "Affenshire", "Affenwich", "Afghan Collie"]]
EDIT: solution by Paulw11 is more efficient
I don't think this question is relevant to swift in particular, but anyways try this:
let a = ["All", "Cat", "red", "gat", "Star sun", "bet you", "Zeta Fog", "Tea", "Fox"]
let b = a.map{ $0.lowercaseString }
let c = b.sort()
let d = c.map{ $0[$0.startIndex.advancedBy(0)]}
var dictionary:[String:[String]] = [:]
let byInitial = d.map{ initial in
let clustered = c.filter{$0.hasPrefix("\(initial)")}
dictionary.updateValue(clustered, forKey:"\(initial)")
}
print("\(dictionary)")

Convert String Array to JSON or 2D Array SWIFT

I currently have a NSMutableArray "localArray" and I am trying to create that into a JSON Array or a 2D Array. I get this data my creating a database and running a query using a for loop on the database.
{
Food,
Burger,
3.99,
1.25,
POP,
Crush,
1.99,
.89,
and more.
}
The reason why I am looking for a JSON or 2d Array is I want to hold the data in the localArray in such a way that I can identify by type and then do something like .valueForKey("Name") or .valurForKey("Price") and add that to my tableview's cell text label or labels.
{
{
Type Food,
Name Burger,
Price 3.99,
Cost 1.25,
},
{
Type POP,
Name Crush,
Price 1.99,
Cost .89,
},
and more
}
I have already tried JSONSerialization, but that failed and also tried 2d Array but no luck.
Any help will be highly appreciated.
This is how I Query and add the data to localArray
let queryType = data.select(ada, code, name, proof, size, case_size, price)
.filter(bevType == type)
let rows = Array(queryType)
for row in rows{
let name = row[self.name]
let type = row[self.type]
let cost = row[self.cost]
let price = row[self.price]
localArray.addObject(name)
localArray.addObject(type)
localArray.addObject(cost)
localArray.addObject(price)
}
I solved it myself by creating a dictionary.
for row in rows{
var rDict: Dictionary = [String: String]()
rDict["Name"] = row[self.name]
rDict["Type"] = row[self.type]
rDict["Cost"] = row[self.cost]
rDict["Price"] = row[self.price]
localArray.addObject(rDict)
}
If fields are always repeating in count of 4, you can try doing this:
var array = [[String: AnyObject]]()
for var i = 0 ; i < array.count ; i += 4 {
var k = 0
var dict = [String: AnyObject]
dict["Type"] = array[i + k++]
dict["Name"] = array[i + k++]
dict["Price"] = array[i + k++]
dict["Cost"] = array[i + k]
array.append(dict)
}
Then extract dictionary from this swift array and use same keys to extract data from dictionary to be used in your cell like
let dict = array[indexPath.row]
cell.title = dict["Name"]

How to append associative array elements in Swift

How do I create and append to an associative array in Swift? I would think it should be something like the following (note that some values are strings and others are numbers):
var myArray = []
var make = "chevy"
var year = 2008
var color = "red"
myArray.append("trackMake":make,"trackYear":year,"trackColor":color)
The goal is to be able to have an array full of results where I can make a call such as:
println(myArray[0]["trackMake"]) //and get chevy
println(myArray[0]["trackColor"]) //and get red
Simply like this:
myArray.append(["trackMake":make,"trackYear":year,"trackColor":color])
Add the brackets. This will make it a hash and append that to the array.
In such cases make (extensive) use of let:
let dict = ["trackMake":make,"trackYear":year,"trackColor":color]
myArray.append(dict)
The above assumes that your myArray has been declared as
var myArray = [[String:AnyObject]]()
so the compiler knows that it will take dictionary elements.
I accept above answer.It is good.Even you have given correct answer,I like to give simplest way.The following steps are useful,if you guys follow that.Also if someone new in swift and if they go through this,they can easily understand the steps.
STEP 1 : Declare and initialize the variables
var array = Array<AnyObject>()
var dict = Dictionary<String, AnyObject>()
var make = "chevy"
var year = 2008
var color = "red"
STEP 2 : Set the Dictionary(adding keys and Values)
dict["trackMake"] = make
dict["trackYear"] = year
dict["trackColor"] = color
println("the dict is-\(dict)")
STEP 3 : Append the Dictionary to Array
array.append(dict)
println("the array is-\(array)")
STEP 4 : Get Array values to variable(create the variable for getting value)
let getMakeValue = array[0]["trackMake"]
let getYearValue = array[0]["trackYear"]
let getColorValue = array[0]["trackColor"]
println("the getMakeValue is - \(getMakeValue)")
println("the getYearValue is - \(getYearValue)")
println("the getColorVlaue is - \(getColorValue)")
STEP 5: If you want to get values to string, do the following steps
var stringMakeValue:String = getMakeValue as String
var stringYearValue:String = ("\(getYearValue as Int)")
var stringColorValue:String = getColorValue as String
println("the stringMakeValue is - \(stringMakeValue)")
println("the stringYearValue is - \(stringYearValue)")
println("the stringColorValue is - \(stringColorValue)")
STEP 6 : Finally the total output values are
the dict is-[trackMake: chevy, trackColor: red, trackYear: 2008]
the array is-[{
trackColor = red;
trackMake = chevy;
trackYear = 2008;
}]
the getMakeValue is - Optional(chevy)
the getYearValue is - Optional(2008)
the getColorVlaue is - Optional(red)
the stringMakeValue is - chevy
the stringYearValue is - 2008
the stringColorValue is - red
Thank You
This sounds like you are wanting an array of objects that represent vehicles. You can either have an array of dictionaries or an array of vehicle objects.
Likely you will want to go with an object as Swift arrays and dictionaries must be typed. So your dictionary with string keys to values of differing types would end up having the type [String : Any] and you would be stuck casting back and forth. This would make your array of type [[String : Any ]].
Using an object you would just have an array of that type. Say your vehicle object's type is named Vehicle, that would make your array of type [Vehicle] and each array access would return an instance of that type.
If I want to try it with my own statement. Which also I want to extend my array with the data in my dictionary and print just the key from dictionary:
var myArray = ["Abdurrahman","Yomna"]
var myDic: [String: Any] = [
"ahmed": 23,
"amal": 33,
"fahdad": 88]
for index in 1...3 {
let dict: [String: Any] = [
"key": "new value"
]
// get existing items, or create new array if doesn't exist
var existingItems = myDic[myArray] as? [[String: Any]] ?? [[String: Any]]()
// append the item
existingItems.append(myArray)
// replace back into `data`
myDic[myArray] = existingItems
}

Resources