Hibernia Hibernia - 2 months ago 17
Swift Question

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?

Firebase Edit:

baseRef looks like

User
rooms

room1 = true
room2 = true


refEach looks like:

Rooms
room1
users
points
displayname
etc.
room2
users
points
displayname
etc.


baseRef.child("rooms").observeSingleEventOfType(.Value) { (snapshot: FIRDataSnapshot) in

// Going into my rooms node and getting snap.keys to use in my next query

if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshots {

let Key = snap.key

let each = Each()
let title = snap.key.uppercaseString
each.title = title


// Using the key from above to go through rooms with that child in another part of my Database

refEach.child(Key).observeSingleEventOfType(.Value, withBlock: { (snapshot: FIRDataSnapshot) in

// grabbing the last user from a simple lastUser = "Someone"


if let lastuser = snapshot.value!["newest"] as? Int {
each.latestUser = lastuser

print("")} else {

}
// This is a users node that has information about each user under th rooms, so I'm making a dictionary out of it and then pulling data as needed.

// I'm trying to go down into the user of each room and find the user with the most points in each room to display. This node looks like Users ---> UIDS ---> points/displayname/etc.
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])

//
// 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
// }


dispatch_async(dispatch_get_main_queue(), {

self.tableView.reloadData()
})

})

leo leo
Answer

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

Comments