0

I have a Dictionary of type [String: Int] and its value is

let dic = [“a”:4, “b”:3, “c”:3]

I want to sort the dictionary by value and using method

dic  = dic.sorted(by: { $0.value < $1.value })

Result

dic = [“c”:3, “b”:3, “a”:4]

It is sorting the dictionary but i want the values which are same should not to be sort or change their order, for example, I want this result

dic = [“b”:3, “c”:3, “a”:4]
Mujahid Latif
  • 596
  • 7
  • 18

2 Answers2

2

Dictionary is unordered. This means that whatever order you see the KVPs in code is not guaranteed to be maintained. The sort call only says to sort by values, so the keys can be in whatever order they want.

Also note that Swift's sorted(by:) is not stable. This means things that are considered equal are not guaranteed to maintain their order.

Therefore, you can't really do anything about it if you insist on using Swift's built in algorithms. You could write an insertion sort (a stable sorting algorithm) yourself and use it though.

Another solution is to order the KVPs by values, then by keys:

let newDict = dict.sorted(by: { $0.value == $1.value ? $0.key < $1.key : $0.value < $1.value })

Obviously this will only work if your player names are ordered lexicographically originally.

Alternatively, create a Player struct and use an array of Players:

struct Player {
    let name: String
    var score: Int
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
2

The main problem here is that dictionary is an unordered collection, so trying to sort it is not the best thing to do.

If you want to store the score values for your game (for a leader-board i.e.) you can use tuples.

typealias Score = (username: String, score: Int)

Then use can create an array of that tuples and sort them any way you want.

var scores = [Score]()

// fill the scores
scores.append(("a", 4))
scores.append(("b", 3))
scores.append(("c", 3))

scores.sort {
    return $0.score < $1.score || ($0.score == $1.score && $0.username.localizedCaseInsensitiveCompare($1.username) == .orderedAscending)
}
Yury Imashev
  • 2,068
  • 1
  • 18
  • 32