Extract the elements from array and put back them to another array.? - swift

suppose i have a array that have 10 elements. say,
var ArrayElemts : ["1","2","3","4","5","6","7","8","9","10","11"]
Now how can i keep the elements from 0 t0 5 in one array set and 6 to 10 to another array set?

Use [0...5] to create an ArraySlice and then Array to convert that back to an array:
var arrayElemts = ["1","2","3","4","5","6","7","8","9","10","11"]
let first = Array(arrayElemts[0...5])
let second = Array(arrayElemts[6...10])
print(first) // ["1", "2", "3", "4", "5", "6"]
print(second) // ["7", "8", "9", "10", "11"]

The easiest option is the following:
let partition1 = array.filter { Int($0) ?? 0 <= 5 }
let partition2 = array.filter { Int($0) ?? 0 > 5 }
Conversion to numbers should be the first step though. You should never work with strings as if they were numbers.
let numbers = array.flatMap { Int($0) }
let partition1 = numbers.filter { $0 <= 5 }
let partition2 = numbers.filter { $0 > 5 }
If we suppose the array is sorted, there are easier options:
let sorted = numbers.sorted()
let partition1: [Int]
let partition2: [Int]
if let partition2start = sorted.index(where: { $0 > 5 }) {
partition1 = Array(sorted.prefix(upTo: partition2start))
partition2 = Array(sorted.suffix(from: partition2start))
} else {
partition1 = sorted
partition2 = []
}
which is what the native partition method can do:
var numbers = array.flatMap { Int($0) }
let index = numbers.partition { $0 > 5 }
let partition1 = Array(numbers.prefix(upTo: index))
let partition2 = Array(numbers.suffix(from: index))
Note the method changes the original array.

Breaking the array up into N-sized chunks
The other answers show you how to "statically" partition the original array in different arrays using ArraySlice:s. Given your description, possibly you want to, generally, break up your original array into N-sized chunks (here: n = 5).
We could use the sequence(state:next) to implement such a chunk(bySize:) method as an extension to Collection:
extension Collection {
func chunk(bySize size: IndexDistance) -> [SubSequence] {
precondition(size > 0, "Chunk size must be a positive integer.")
return sequence(
state: (startIndex, index(startIndex, offsetBy: size, limitedBy: endIndex) ?? endIndex),
next: { indices in
guard indices.0 != self.endIndex else { return nil }
indices.1 = self.index(indices.0, offsetBy: size, limitedBy: self.endIndex) ?? self.endIndex
return (self[indices.0..<indices.1], indices.0 = indices.1).0
}).map { $0 }
}
}
Applied to your example:
var arrayElements = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]
let partitions = arrayElements.chunk(bySize: 5)
/* [["1", "2", "3", "4", "5"],
["6", "7", "8", "9", "10"],
["11"]] */
The chunk(bySize:) method will break up the array into bySize-sized chunks, as well as (possible) a smaller chunk for the final partition.
However, as much as I'd like to try to use the sequence(state:next) function (not needing to use any mutable intermediate variables other than state), the implementation above is quite bloated and difficult to read, so (as for so many other cases ...) we are probably better off simply using a while loop:
extension Collection {
func chunk(bySize size: IndexDistance) -> [SubSequence] {
precondition(size > 0, "Chunk size must be a positive integer.")
var chunks: [SubSequence] = []
var from = startIndex
while let to = index(from, offsetBy: size, limitedBy: endIndex) {
chunks.append(self[from..<to])
from = to
}
if from != endIndex { chunks.append(self[from..<endIndex]) }
return chunks
}
}

lol I don't see why there are so complicated answers here
(Consider the "array" variable as is -> [Int], not [Any])
So the first approach is just for Number types.
The second one should do it
Simply:
let array = [0,1,2,3,4,5,6,7,8,9,10]
//For instance..
var arrayA = ["A","B","C","D","E","F","G"]
//First 6 elements
let arrayOfFirstFour = array.filter({
return $0 <= 5 ? true : false
})
//Remaining elements:
let restOfArray = array.filter({
return $0 > 5 ? true : false
})
let elementsToFourth = arrayA.prefix(upTo: 4)
let elementsAfterFourth = arrayA.suffix(from: 4)
print(arrayOfFirstFour)
print(restOfArray)
print(elementsToFourth)
print(elementsAfterFourth)
//[0, 1, 2, 3, 4, 5]
//[6, 7, 8, 9, 10]
//["A", "B", "C", "D"]
//["E", "F", "G"]

Related

How to perform sorting on an array without using .sort()

I am trying to find the easiest way to sort an array without using sort() function. I tried searching but i could not find any questions that were on SWIFT. I found several questions about php and javascript and so far nothing on swift.
var arr = [7,6456,2135,164,1345,4,8,5,87456,123,2,87,724,6523,1]
var arrSorted = arr
var index = arr.count
repeat {
var previousSwapIndex = 0
for i in 1..<index {
if (arrSorted[i - 1] as! Int) > (arrSorted[i] as! Int) {
let prevVal = arrSorted[i - 1]
let currentVal = arrSorted[i]
arrSorted[i] = prevVal
arrSorted[i - 1] = currentVal
previousSwapIndex = i
}
}
index = previousSwapIndex
} while (index != 0)
print(arrSorted as Array)
This method works but i am looking for something that is better than this and easier than this.
(Edit[Clarification] :- better = faster / quicker ,as this iterates 120 times before the array is sorted)
Could someone help me out?
Here's a generic implementation of insertion sort in Swift. It takes an inout array, but you should be able to modify it to return an array if that's what you want.
func sort<T: Comparable>(_ array: inout [T]) {
var i = 1
while i < array.count {
var x = array[i]
var j = i - 1
while j >= 0 && array[j] > x {
array[j+1] = array[j]
j -= 1
}
array[j+1] = x
i += 1
}
}
To use it:
var intArr = [1, 7, 3, 6, 4]
sort(&intArr)
print(intArr) // [1, 3, 4, 6, 7]
var stringArr = ["hello", "goodbye", "a", "string", "z", "another string"]
sort(&stringArr)
print(stringArr) // ["a", "another string", "goodbye", "hello", "string", "z"]
It will work on any type that conforms to Comparable.
You can find about all the different methods of sorting from this git.
https://github.com/raywenderlich/swift-algorithm-club
I checked a few and none of them are using any .sort() functions. Pick whichever feels easier for you.
var unsortedStringArray = ["B", "C", "Z", "A", "H"]
var unsortedIntArray = [7,8,3,4,5,9,1,2,6]
func sortFunction<T:Comparable>(array: [T]) -> [T]{
var unsortedArray = array
for i in 0..<unsortedArray.count {
for j in 0..<unsortedArray.count{
var temp: T
if unsortedArray[i] < unsortedArray[j] {
temp = unsortedArray[i]
unsortedArray[i] = unsortedArray[j]
unsortedArray[j] = temp
}
}
}
return unsortedArray
}
let resultStringArray = sortFunction(array: unsortedStringArray)
let resultIntArray = sortFunction(array: unsortedIntArray)
print(resultStringArray) //["A", "B", "C", "H", "Z"]
print(resultIntArray) // [1, 2, 3, 4, 5, 6, 7, 8, 9]

Get all values into dictionary and create a String with a specific format

I have a dictionary with this structure:
a: [1,2]
b: [3,4]
c: [5,6]
and I need to return a string with this structure.
a,b,c\n1,3,5\n2,4,6
I solved the first part of the string. But to get the rest of the String. I try to iterate into my dictionary to get the first elements for each key in my dictionary and then get the rest for each value into the array.
Is there an easier way to get this?
Once you know what's the order of the keys (alpha ?), you can use this:
let dict: [String: [Int]] = ["a": [1,2], "b": [3, 4], "c": [5, 6]]
let keys = dict.keys.sorted() //Or do whatever you want here to get your target order
var matrix: [[String]] = []
keys.forEach {
guard let arrayAsInt = dict[$0] else { return }
let arrayAsString = arrayAsInt.map{ "\($0)" }
matrix.append( [$0] + arrayAsString)
}
print("Matrix: \(matrix)")
let transposed = matrix.transposed()
print("Transposed Matrix: \(transposed)")
let output = transposed.map { $0.joined(separator: ",")}.joined(separator: "\n")
print(output)
The outputs:
$>Matrix: [["a", "1", "2"], ["b", "3", "4"], ["c", "5", "6"]]
$>Transposed Matrix: [["a", "b", "c"], ["1", "3", "5"], ["2", "4", "6"]]
$>a,b,c
1,3,5
2,4,6
Obvisouly the "\n" might be invisible and be an actual new line
a,b,c
1,3,5
2,4,6
Being
a,b,c\n1,3,5\n2,4,6
What's the idea behind that? Create a matrix and use the transpose (it's used in maths with matrix, it's one of the basic modification of a matrix).
First transform the [String: [Int]] into a [[String]], where each element would be key followed by its values. I transformed it there as String for simpler code later.
Why doing that? Because the matrix value is easy to get from your initial dict. the transposed value is harder (not impossible) to get from dict but easier from matrix, and the transposed is quickly transformed into your format.
So my thinking was the reverse:
Get a structure from your output, then how to get it, it's a transpose, so I need to get the initial input as it, etc.
With the help of a code for Transpose Matrix (that accept String elements).
extension Collection where Self.Iterator.Element: RandomAccessCollection {
// PRECONDITION: `self` must be rectangular, i.e. every row has equal size.
func transposed() -> [[Self.Iterator.Element.Iterator.Element]] {
guard let firstRow = self.first else { return [] }
return firstRow.indices.map { index in
self.map{ $0[index] }
}
}
}
Any code (there a various) working ones, should the trick. I took it from here.
As pointed by #Leo Dabus, you can remove the Self.Iterator.Element
from the extension code (twice). I just wanted to it as such, not modifying the initial answer since it's not mind.
What you are looking for, besides composing the final string, is how to transpose a collection (this would work with collections of different sizes as well):
extension Sequence {
func max<T: Comparable>(_ predicate: (Element) -> T) -> Element? {
self.max(by: { predicate($0) < predicate($1) })
}
}
extension Collection where Element: RandomAccessCollection, Element.Indices == Range<Int> {
func transposed() -> [[Element.Element]] {
(0..<(max(\.count)?.count ?? .zero)).map {
index in compactMap { $0.indices ~= index ? $0[index] : nil }
}
}
}
let dict = ["a": [1,2,3],
"b": [4,5,6],
"c": [7,8,9]]
let sorted = dict.sorted(by: {$0.key < $1.key})
let result = sorted.map(\.key).joined(separator: ",") + "\n" +
sorted.map(\.value).transposed().map {
$0.map(String.init).joined(separator: ",")
}.joined(separator: "\n")
result // "a,b,c\n1,4,7\n2,5,8\n3,6,9"
A dictionary is an unordered collection so you need to sort it according to any specific key. Here I sort the dictionary according to the key if you don't care about an order you can just remove sort.
let dict: [String: Any] = ["a": [1,2], "b": [3,4], "c": [5,6]]
let sortedKey = dict.keys.sorted(by: <)
let key = sortedKey.joined(separator: ",")
var firstValues: [String] = []
var secondValues: [String] = []
sortedKey.forEach { (key) in
if let dictValue = dict[key] as? [Int],
let firstValue = dictValue.first,
let secondValue = dictValue.last {
firstValues.append("\(firstValue)")
secondValues.append("\(secondValue)")
}
}
let finalString = key + "\n" + firstValues.joined(separator: ",") + "\n" + secondValues.joined(separator: ",")
print(finalString) // "a,b,c\n1,3,5\n2,4,6"

Repeat a specific item of an array

How to replace or repeat a specific item (v) of an array in Swift 3 / 4:
["A","s","B","v","C","s","D","v","E","s"]
to get this:
["A","s","B","v","v","C","s","D","v","v","E","s"]
or this:
["A","s","B","v","v","v","C","s","D","v","v","v","E","s"]
["A","s","B","v","v","v","v","C","s","D","v","v","v","v","E","s"]
The reason is that element v inserts pauses (sec) between audio files (A, B, C, ...). The number of repetitions of the item v should be set via a SegmentedControl (1,2, ..., 6).
Quick takeaway
extension Array where Element == String {
func repeatItem(_ item: Element, times n: Int) -> Array<Element> {
return flatMap { $0 == item ? Array(repeating: $0, count: n) : [$0] }
}
}
Detail explains
Use flatMap:
yourArray.flatMap { $0 == "v" ? [$0, $0] : [$0] }
Basically, this checks each element of the array. If it is "v", turn it into ["v", "v"]. If it is not "v", turn it into an array with that single element. Then it flattens all those arrays, hence flatMap.
You can also triple a specific item:
yourArray.flatMap { $0 == "v" ? [$0, $0, $0] : [$0] }
Or repeat it n times:
yourArray.flatMap { $0 == "v" ? Array(repeating: $0, count: n) : [$0] }
Use playground to verify it:
//: Playground - noun: a place where people can play
import Foundation
var inputArray = ["A","s","B","v","C","s","D","v","E","s"]
var expectArray2 = ["A","s","B","v","v","C","s","D","v","v","E","s"]
var expectArray3 = ["A","s","B","v","v","v","C","s","D","v","v","v","E","s"]
var expectArray4 = ["A","s","B","v","v","v","v","C","s","D","v","v","v","v","E","s"]
extension Array where Element == String {
func repeatItem(_ item: Element, times n: Int) -> Array<Element> {
return flatMap { $0 == item ? Array(repeating: $0, count: n) : [$0] }
}
}
print(inputArray.repeatItem("v", times: 2) == expectArray2)
print(inputArray.repeatItem("v", times: 3) == expectArray3)
print(inputArray.repeatItem("v", times: 4) == expectArray4)
You can use insert(:at:) using the specific index of an element.
var foo = [0,1,2,3,4,5,6,7]
foo.insert(0, at: foo[0])
Output
[0, 0, 1, 2, 3, 4, 5, 6, 7]
You can wrap this in a function to repeat as much as you need.
let array : [String] = ["A","s","B","v","C","s","D","v","E","s"]
print(replaceItem(array: array, item: "v"))
//Method
func replaceItem(array : [String], item : String) -> [String] {
var newAr: [String] = []
for arItem in array{
newAr.append(arItem)
if arItem == item {
newAr.append(arItem)
}
}
return newAr
}
output :
["A", "s", "B", "v", "v", "C", "s", "D", "v", "v", "E", "s"]

Hex String to Character in PURE Swift

I need a way to convert a string that contains a literal string representing a hexadecimal value into a Character corresponding to that particular hexadecimal value.
Ideally, something along these lines:
let hexString: String = "2C"
let char: Character = fromHexString(hexString)
println(char) // prints -> ","
I've tried to use the syntax: "\u{n}" where n is a Int or String and neither worked.
This could be used to loop over an array of hexStrings like so:
var hexArray = ["2F", "24", "40", "2A"]
var charArray = [Character]()
charArray = map(hexArray) { charArray.append(Character($0)) }
charArray.description // prints -> "[/, $, #, *]"
A couple of things about your code:
var charArray = [Character]()
charArray = map(hexArray) { charArray.append(Character($0)) }
You don't need to create an array and then assign the result of the map, you can just assign the result and avoid creating an unnecessary array.
charArray = map(hexArray) { charArray.append(Character($0)) }
Here you can use hexArray.map instead of map(hexArray), also when you use a map function what you are conceptually doing is mapping the elements of the receiver array to a new set of values and the result of the mapping is the new "mapped" array, which means that you don't need to do charArray.append inside the map closure.
Anyway, here is a working example:
let hexArray = ["2F", "24", "40", "2A"]
var charArray = hexArray.map { char -> Character in
let code = Int(strtoul(char, nil, 16))
return Character(UnicodeScalar(code))
}
println(charArray) // -> [/, $, #, *]
EDIT: This is another implementation that doesn't need Foundation:
func hexToScalar(char: String) -> UnicodeScalar {
var total = 0
for scalar in char.uppercaseString.unicodeScalars {
if !(scalar >= "A" && scalar <= "F" || scalar >= "0" && scalar <= "9") {
assertionFailure("Input is wrong")
}
if scalar >= "A" {
total = 16 * total + 10 + scalar.value - 65 /* 'A' */
} else {
total = 16 * total + scalar.value - 48 /* '0' */
}
}
return UnicodeScalar(total)
}
let hexArray = ["2F", "24", "40", "2A"]
var charArray = hexArray.map { Character(hexToScalar($0)) }
println(charArray)
EDIT2 Yet another option:
func hexToScalar(char: String) -> UnicodeScalar {
let map = [ "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
"A": 10, "B": 11, "C": 12, "D": 13, "E": 14, "F": 15 ]
let total = reduce(char.uppercaseString.unicodeScalars, 0, { $0 * 16 + (map[String($1)] ?? 0xff) })
if total > 0xFF {
assertionFailure("Input char was wrong")
}
return UnicodeScalar(total)
}
Final edit: explanation
Given that the ascii table has all the number together (012345679), we can convert 'N' (base 10) to an integer knowing the ascii value of 0.
Because:
'0': 48
'1': 49
...
'9': 57
Then if for example you need to convert '9' to 9 you could do
asciiValue('9') - asciiValue('0') => 57 - 48 = 9
And you can do the same from 'A' to 'F':
'A': 65
'B': 66
...
'F': 70
Now we can do the same as before but, for example for 'F' we'd do:
asciiValue('F') - asciiValue('A') => 70 - 65 = 5
Note that we need to add 10 to this number to get the decimal. Then (going back to the code): If the scalar is between A-Z we need to do:
10 + asciiValue(<letter>) - asciiValue('A')
which is the same as: 10 + scalar.value - 65
And if it's between 0-9:
asciiValue(<letter>) - asciiValue('0')
which is the same as: scalar.value - 48
For example: '2F'
'2' is 2 and 'F' is 15 (by the previous example), right?. Since hex is base 16 we'd need to do:
((16 ^ 1) * 2) + ((16 ^ 0) * 15) = 47
Here you go:
var string = String(UnicodeScalar(Int("2C", radix: 16)!))
BTW, you can include hex values in the literal strings like this:
var string = "\u{2c}"
With Swift 5, you will have to convert your string variable into an integer (using init(_:radix:) initializer), create Unicode scalar from this integer (using init(_:)) then create a character from this Unicode scalar (using init(_:)).
The Swift 5 Playground sample code below shows how to proceed:
let validHexString: String = "2C"
let validUnicodeScalarValue = Int(validHexString, radix: 16)!
let validUnicodeScalar = Unicode.Scalar(validUnicodeScalarValue)!
let character = Character(validUnicodeScalar)
print(character) // prints: ","
If you want to perform this operation for the elements inside an array, you can use the sample code below:
let hexArray = ["2F", "24", "40", "2A"]
let characterArray = hexArray.map({ (hexString) -> Character in
let unicodeScalarValue = Int(hexString, radix: 16)!
let validUnicodeScalar = Unicode.Scalar(unicodeScalarValue)!
return Character(validUnicodeScalar)
})
print(characterArray) // prints: ["/", "$", "#", "*"]
Alternative with no force unwraps:
let hexArray = ["2F", "24", "40", "2A"]
let characterArray = hexArray.compactMap({ (hexString) -> Character? in
guard let unicodeScalarValue = Int(hexString, radix: 16),
let unicodeScalar = Unicode.Scalar(unicodeScalarValue) else {
return nil
}
return Character(unicodeScalar)
})
print(characterArray) // prints: ["/", "$", "#", "*"]
Another simple way based on ICU transforms:
extension String {
func transformingFromHex() -> String? {
return "&#x\(self);".applyingTransform(.toXMLHex, reverse: true)
}
}
Usage:
"2C".transformingFromHex()
Results in: ,

Sort Dictionary by values in Swift

Is there are analog of - (NSArray *)keysSortedByValueUsingSelector:(SEL)comparator in swift?
How to do this without casting to NSDictionary?
I tried this, but it seems to be not a good solution.
var values = Array(dict.values)
values.sort({
$0 > $1
})
for number in values {
for (key, value) in dict {
if value == number {
println(key + " : \(value)");
dict.removeValueForKey(key);
break
}
}
}
Example:
var dict = ["cola" : 10, "fanta" : 12, "sprite" : 8]
dict.sortedKeysByValues(>) // fanta (12), cola(10), sprite(8)
Just one line code to sort dictionary by Values in Swift 4, 4.2 and Swift 5:
let sortedByValueDictionary = myDictionary.sorted { $0.1 < $1.1 }
Try:
let dict = ["a":1, "c":3, "b":2]
extension Dictionary {
func sortedKeys(isOrderedBefore:(Key,Key) -> Bool) -> [Key] {
return Array(self.keys).sort(isOrderedBefore)
}
// Slower because of a lot of lookups, but probably takes less memory (this is equivalent to Pascals answer in an generic extension)
func sortedKeysByValue(isOrderedBefore:(Value, Value) -> Bool) -> [Key] {
return sortedKeys {
isOrderedBefore(self[$0]!, self[$1]!)
}
}
// Faster because of no lookups, may take more memory because of duplicating contents
func keysSortedByValue(isOrderedBefore:(Value, Value) -> Bool) -> [Key] {
return Array(self)
.sort() {
let (_, lv) = $0
let (_, rv) = $1
return isOrderedBefore(lv, rv)
}
.map {
let (k, _) = $0
return k
}
}
}
dict.keysSortedByValue(<)
dict.keysSortedByValue(>)
Updated:
Updated to the new array syntax and sort semantics from beta 3. Note that I'm using sort and not sorted to minimize array copying. The code could be made more compact, by looking at the earlier version and replacing sort with sorted and fixing the KeyType[] to be [KeyType]
Updated to Swift 2.2:
Changed types from KeyType to Key and ValueType to Value. Used new sort builtin to Array instead of sort(Array) Note performance of all of these could be slightly improved by using sortInPlace instead of sort
You could use something like this perhaps:
var dict = ["cola" : 10, "fanta" : 12, "sprite" : 8]
var myArr = Array(dict.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
}
myArr // ["fanta", "cola", "sprite"]
This should give you the sorted keys based on value, and is a little more cleaner:
var sortedKeys = Array(dict.keys).sorted(by: { dict[$0]! < dict[$1]! })
I think this is the easiest way to sort Swift dictionary by value.
let dict = ["apple":1, "cake":3, "banana":2]
let byValue = {
(elem1:(key: String, val: Int), elem2:(key: String, val: Int))->Bool in
if elem1.val < elem2.val {
return true
} else {
return false
}
}
let sortedDict = dict.sort(byValue)
OneLiner :
let dict = ["b": 2, "a": 1, "c": 3]
(Array(dict).sorted { $0.1 < $1.1 }).forEach { (k,v) in print("\(k):\(v)") }
//Output: a:1, b:2, c:3
Swap out the .forEach with .map -> Functional programming
Syntactical sugar :
extension Dictionary where Value: Comparable {
var sortedByValue: [(Key, Value)] { return Array(self).sorted { $0.1 < $1.1} }
}
extension Dictionary where Key: Comparable {
var sortedByKey: [(Key, Value)] { return Array(self).sorted { $0.0 < $1.0 } }
}
["b": 2, "a": 1, "c": 3].sortedByKey // a:1, b:2, c:3
["b": 2, "a": 1, "c": 3].sortedByValue // a:1, b:2, c:3
Lots of answers, here's a one-liner. I like it because it makes full use of native Swift iterative functions and doesn't use variables. This should help the optimiser do its magic.
return dictionary.keys.sort({ $0 < $1 }).flatMap({ dictionary[$0] })
Note the use of flatMap, because subscripting a dictionary returns an optional value. In practice this should never return nil since we get the key from the dictionary itself. flatMap is there only to ensure that the result is not an array of optionals. If your array's associated value should BE an optional you can use map instead.
Sorting your keys by the dictionary's value is actually simpler than it appears at first:
let yourDict = ["One": "X", "Two": "B", "Three": "Z", "Four": "A"]
let sortedKeys = yourDict.keys.sort({ (firstKey, secondKey) -> Bool in
return yourDict[firstKey] < yourDict[secondKey]
})
And that's it! There's really nothing more to it. I have yet to find a quicker method, other than the same approach in form of a simple one-liner:
let yourDict = ["One": "X", "Two": "B", "Three": "Z", "Four": "A"]
let sortedKeys = yourDict.keys.sort { yourDict[$0] < yourDict[$1] }
Sorting a dictionary by key or value
Using Swift 5.2 internal handling of "sorted":
var unsortedDict = ["cola" : 10, "fanta" : 12, "sprite" : 8]
// sorting by value
let sortedDictByValue = unsortedDict.sorted{ $0.value > $1.value } // from lowest to highest using ">"
print("sorted dict: \(sortedDictByValue)")
// result: "sorted dict: [(key: "fanta", value: 12), (key: "cola", value: 10), (key: "sprite", value: 8)]\n"
// highest value
print(sortedDictByValue.first!.key) // result: fanta
print(sortedDictByValue.first!.value) // result: 12
// lowest value
print(sortedDictByValue.last!.key) // result: sprite
print(sortedDictByValue.last!.value) // result: 8
// by index
print(sortedDictByValue[1].key) // result: cola
print(sortedDictByValue[1].value) // result: 10
// sorting by key
let sortedDictByKey = unsortedDict.sorted{ $0.key < $1.key } // in alphabetical order use "<"
// alternative:
// let sortedDictByKey = unsortedDict.sorted{ $0 < $1 } // without ".key"
print("sorted dict: \(sortedDictByKey)")
// result: "sorted dict: [(key: "cola", value: 10), (key: "fanta", value: 12), (key: "sprite", value: 8)]\n"
// highest value
print(sortedDictByKey.first!.key) // result: cola
print(sortedDictByKey.first!.value) // result: 10
// lowest value
print(sortedDictByKey.last!.key) // result: sprite
print(sortedDictByKey.last!.value) // result: 8
// by index
print(sortedDictByKey[1].key) // result: fanta
print(sortedDictByKey[1].value) // result: 12
The following might be useful if you want the output to be an array of key value pairs in the form of a tuple, sorted by value.
var dict = ["cola" : 10, "fanta" : 12, "sprite" : 8]
let sortedArrByValue = dict.sorted{$0.1 > $1.1}
print(sortedArrByValue) // output [(key: "fanta", value: 12), (key: "cola", value: 10), (key: "sprite", value: 8)]
Since Swift 3.0 Dictionary has sorted(by:) function which returns an array of tuples ([(Key, Value)]).
let sorted = values.sorted(by: { (keyVal1, keyVal2) -> Bool in
keyVal1.value > keyVal2.value
})
Just cast it to NSDictionary and then call the method. Anywhere you use #selector in ObjC you can just use a String in Swift. So it would look like this:
var dict = ["cola" : 10, "fanta" : 12, "sprite" : 8]
let sortedKeys = (dict as NSDictionary).keysSortedByValueUsingSelector("compare:")
or
let sortedKeys2 = (dict as NSDictionary).keysSortedByValueUsingComparator
{
($0 as NSNumber).compare($1 as NSNumber)
}
As of Swift 3, to sort your keys based on values, the below looks promising:
var keys = Array(dict.keys)
keys.sortInPlace { (o1, o2) -> Bool in
return dict[o1]! as! Int > dict[o2]! as! Int
}
var dict = ["cola" : 10, "fanta" : 12, "sprite" : 8]
let arr = dic.sort{ (d1,d2)-> Bool in
if d1.value > d2.value {
retrn true
}
}.map { (key,value) -> Int in
return value
}
Take look a clean implementation way.
print("arr is :(arr)")
The following way in Swift 3 sorted my dictionary by value in the ascending order:
for (k,v) in (Array(dict).sorted {$0.1 < $1.1}) {
print("\(k):\(v)")
}
SWIFT 3:
Using a few resources I put this beautifully short code together.
dictionary.keys.sorted{dictionary[$0]! < dictionary[$1]!}
This returns an array of the dictionary keys sorted by their values. It works perfectly & doesn't throw errors when the dictionary is empty. Try this code in a playground:
//: Playground - noun: a place where people can play
import UIKit
let dictionary = ["four": 4, "one": 1, "seven": 7, "two": 2, "three": 3]
let sortedDictionary = dictionary.keys.sorted{dictionary[$0]! < dictionary[$1]!}
print(sortedDictionary)
// ["one", "two", "three", "four", "seven"]
let emptyDictionary = [String: Int]()
let emptyDictionarySorted = emptyDictionary.keys.sorted{emptyDictionary[$0]! < emptyDictionary[$1]!}
print(emptyDictionarySorted)
// []
If you'd like some help on why the heck the code uses $0, $1 and doesn't even have parentheses after the "sorted" method, check out this post - https://stackoverflow.com/a/34785745/7107094
This is how I did it - sorting in this case by a key called position. Try this in a playground:
var result: [[String: AnyObject]] = []
result.append(["name" : "Ted", "position": 1])
result.append(["name" : "Bill", "position": 0])
result
result = sorted(result, positionSort)
func positionSort(dict1: [String: AnyObject], dict2: [String: AnyObject]) -> Bool {
let position1 = dict1["position"] as? Int ?? 0
let position2 = dict2["position"] as? Int ?? 0
return position1 < position2
}
Sorting the dictionary with a dictionary as the value (Nested dictionary)
var students: [String: [String: Any?]] = ["16CSB40" : ["Name": "Sunitha", "StudentId": "16CSB40", "Total": 90], "16CSB41" : ["Name": "Vijay", "StudentId": "16CSB40", "Total": 80], "16CSB42" : ["Name": "Tony", "StudentId": "16CSB42", "Total": 95]] // Sort this dictionary with total value
let sorted = students.sorted { (($0.1["Total"] as? Int) ?? 0) < (($1.1["Total"] as? Int) ?? 0) }
print(sorted) //Sorted result
Use this, and then just loop through the dictionary again using the output keys.
extension Dictionary where Value: Comparable {
func sortedKeysByValue() -> [Key] {
keys.sorted { return self[$0]! < self[$1]! }
}
}
...or this if you hate force unwrapping :)
extension Dictionary where Value: Comparable {
func sortedKeysByValue() -> [Key] {
keys.sorted { (key1, key2) -> Bool in
guard let val1 = self[key1] else { return true }
guard let val2 = self[key2] else { return true }
return val1 < val2
}
}
}