Related
my program takes as input an array of arrays and every array could be of a different type. e.g.
var data = [[1, 2, 3], ["1", "2", "3"], [1.0, 2.0, 3.0]]
print(type(of: data)) // Array<Array<Any>>
From each array in data I would like to automatically infer the correct type. Lets say that data always will contain arrays of either double, int and float. So my protocol is:
public protocol myType {}
extension Int: myType {}
extension Double: myType {}
extension String: myType {}
What I would like to do is store every array in data in a dictionary that conforms to myType
For examples
var dict = Dictionary<AnyHashable, Array<myType>>()
hashTable["0"] = data[0] // error
hashTable["1"] = data[1] // error
hashTable["2"] = data[2] // error
Ofcourse this doesn't work because data[0] is not of myType but of Any type. Is there an easy automated way to cast each array automatically to either int, double or string?
Minor nitpick: The protocol here should be called MyType instead of myType, since convention is for types to start with a capital letter.
With that said, casting to [MyType] should do what you want:
var data = [[1, 2, 3], ["1", "2", "3"], [1.0, 2.0, 3.0]]
public protocol MyType {}
extension Int: MyType {}
extension Double: MyType {}
extension String: MyType {}
var dict: [AnyHashable : [MyType]] = [:]
dict["0"] = data[0] as? [MyType]
dict["1"] = data[1] as? [MyType]
dict["2"] = data[2] as? [MyType]
print(dict)
outputs:
[AnyHashable("2"): [1.0, 2.0, 3.0], AnyHashable("1"): ["1", "2", "3"], AnyHashable("0"): [1, 2, 3]]
I don't think what you are trying to do with your protocol will make any difference, MyType will just be pretty much the same as Any but limited to fewer types. You will still not be able to perform specific actions based on the type of the underlying data.
Instead you need to determine the exact type for each sub-array and then act on that specific type like in the example below
data.forEach {
guard !$0.isEmpty else { return }
switch $0.first {
case _ as Int:
handleIntArray($0 as! [Int])
case _ as Double:
handleDoubleArray($0 as! [Double])
case _ as String:
handleStringArray($0 as! [String])
default:
print("Unsupported type")
}
}
func handleIntArray(_ array: [Int]) {
//...
}
func handleDoubleArray(_ array: [Double]) {
//...
}
func handleStringArray(_ array: [String]) {
//...
}
In my opinion you are going the wrong way. Why would you need to mix collection types inside another collection? Anyway if you realy want to go down this path you need first to make your life easier fixing the main issue of your code that is the fact that you are working with [[Any]]. Change your collection type to [Any] and switch its contents.
let data: [Any] = [[1, 2, 3], ["1", "2", "3"], [1.0, 2.0, 3.0]]
data.forEach {
switch $0 {
case let elements as [Int]:
print("integers:", elements)
case let elements as [Double]:
print("doubles:", elements)
case let elements as [String]:
print("strings:", elements)
default:
print("other object(s):", $0)
}
}
another option if you don't want to change your data type is to cast your array elements to Any when switching it:
let data = [[1, 2, 3], ["1", "2", "3"], [1.0, 2.0, 3.0]]
data.forEach {
switch $0 as Any {
case let elements as [Int]:
print("integers:", elements)
case let elements as [Double]:
print("doubles:", elements)
case let elements as [String]:
print("strings:", elements)
default:
print("other objects:", $0)
}
}
If you would like to get a collection of specific type:
let integers = data.first { $0 is [Int] } as? [Int] ?? []
let strings = data.first { $0 is [String] } as? [String] ?? []
let doubles = data.first { $0 is [Double] } as? [Double] ?? []
extension Sequence {
func firstObjects<T>() -> [T] { first { $0 is [T] } as? [T] ?? [] }
}
let integers: [Int] = data.firstObjects() // [1, 2, 3]
let strings: [String] = data.firstObjects() // ["1", "2", "3"]
let doubles: [Double] = data.firstObjects() // [1, 2, 3]
Or to get all sub collections elements of a certain type:
extension Collection {
func joined() -> [Any] {
flatMap { ($0 as? [Any])?.joined() ?? [$0] }
}
func flatMapped<T>(with type: T.Type? = nil) -> [T] {
joined().compactMap { $0 as? T }
}
}
let integers: [Int] = data.flatMapped() // [1, 2, 3]
let strings: [String] = data.flatMapped() // ["1", "2", "3"]
let doubles: [Double] = data.flatMapped() // [1, 2, 3]
var firstArray = ["1.","2.","3.","4."]
var secondArray = ["a","b","c"]
func combineTheArrays(array1: [Any], array2: [Any]) -> [Any] {
var finalArray = [Any]()
let maxIndex = array1.count >= array2.count ? array1.count : array2.count;
for i in 0...maxIndex{
if (array1.count > i){
finalArray.append(array1[i])
}
if (array2.count > i){
finalArray.append(array2[i])
}
} }
combineTheArrays(array1: firstArray, array2: secondArray)
print(finalArray)
I am trying to take two arrays with different/similar types and have it work through the function and combine into one single array. The ideal result of this func is to print:
finalArray = ["1.", "a", "2.", "b", "3.", "c", "4."]
You're very close! You just need to return finalArray at the end of your function definition, and then assign the result of the function call, so that you can then use it (such as in a print call):
let finalArray = combineTheArrays(array1: firstArray, array2: secondArray)
print(finalArray)
You should also use generics to ensure that you can handle any kind of elements, so long as their types are the same. Unlike returning Any, your result will be an array of the same type, which will be safer and easier to work with. Here is how I would improve this code:
func combineTheArrays<T>(array1: [T], array2: [T]) -> [T] {
let maxIndex = max(array1.count, array2.count);
var finalArray = [T]()
finalArray.reserveCapacity(array1.count + array2.count)
for i in 0..<maxIndex {
if i < array1.count { finalArray.append(array1[i]) }
if i < array2.count { finalArray.append(array2[i]) }
}
return finalArray
}
var firstArray = ["1.","2.","3.","4."]
var secondArray = ["a","b","c"]
let finalArray = combineTheArrays(array1: firstArray, array2: secondArray)
print(finalArray)
I have a large array and need to access it by a key (a lookup) so I need to create Dictionary. Is there a built in function in Swift 3.0 to do so, or do I need to write it myself?
First I will need it for a class with key "String" and later on maybe I will be able to write a template version for general purpose (all types of data and key).
Note for 2019. This is now simply built-in to Swift 5, uniqueKeysWithValues and similar calls.
Is that it (in Swift 4)?
let dict = Dictionary(uniqueKeysWithValues: array.map{ ($0.key, $0) })
Note:
As mentioned in the comment, using uniqueKeysWithValues would give a fatal error (Fatal error: Duplicate values for key: 'your_key':) if you have duplicated keys.
If you fear that may be your case, then you can use init(_:uniquingKeysWith:) e.g.
let pairsWithDuplicateKeys = [("a", 1), ("b", 2), ("a", 3), ("b", 4)] // or `let pairsWithDuplicateKeys = array.map{ ($0.key, $0) }`
let firstValues = Dictionary(pairsWithDuplicateKeys, uniquingKeysWith: { (first, _) in first })
print(firstValues)
//prints ["a": 1, "b": 2]
let lastValues = Dictionary(pairsWithDuplicateKeys, uniquingKeysWith: { (_, last) in last })
print(lastValues)
//prints ["a": 3, "b": 4]
On Swift 4, you can achieve this by using Dictionary's grouping:by: initializer
For ex:
You have class named A
class A {
var name: String
init(name: String) {
self.name = name
}
// .
// .
// .
// other declations and implementions
}
Next, you have an array of objects of type A
let a1 = A(name: "Joy")
let a2 = A(name: "Ben")
let a3 = A(name: "Boy")
let a4 = A(name: "Toy")
let a5 = A(name: "Tim")
let array = [a1, a2, a3, a4, a5]
Let's say you want to create a Dictionary by grouping all the names by their first letter. You use Swifts Dictionary(grouping:by:) to achieve this
let dictionary = Dictionary(grouping: array, by: { $0.name.first! })
// this will give you a dictionary
// ["J": [a1], "B": [a2, a3], "T": [a4, a5]]
source
Note however that the resulting Dictionary "dictionary" is of type
[String : [A]]
it is not of type
[String : A]
as you may expect. (Use #uniqueKeysWithValues to achieve the latter.)
I think you're looking for something like this:
extension Array {
public func toDictionary<Key: Hashable>(with selectKey: (Element) -> Key) -> [Key:Element] {
var dict = [Key:Element]()
for element in self {
dict[selectKey(element)] = element
}
return dict
}
}
You can now do:
struct Person {
var name: String
var surname: String
var identifier: String
}
let arr = [Person(name: "John", surname: "Doe", identifier: "JOD"),
Person(name: "Jane", surname: "Doe", identifier: "JAD")]
let dict = arr.toDictionary { $0.identifier }
print(dict) // Result: ["JAD": Person(name: "Jane", surname: "Doe", identifier: "JAD"), "JOD": Person(name: "John", surname: "Doe", identifier: "JOD")]
If you'd like your code to be more general, you could even add this extension on Sequence instead of Array:
extension Sequence {
public func toDictionary<Key: Hashable>(with selectKey: (Iterator.Element) -> Key) -> [Key:Iterator.Element] {
var dict: [Key:Iterator.Element] = [:]
for element in self {
dict[selectKey(element)] = element
}
return dict
}
}
Do note, that this causes the Sequence to be iterated over and could have side effects in some cases.
As others already said, we need to understand which are the keys.
However I am trying to provide a solution to my interpretation of your question.
struct User {
let id: String
let firstName: String
let lastName: String
}
Here I am assuming that 2 users with the same id cannot exist
let users: [User] = ...
let dict = users.reduce([String:User]()) { (result, user) -> [String:User] in
var result = result
result[user.id] = user
return result
}
Now dict is a dictionary where the key is the user id and the value is the user value.
To access a user via its id you can now simply write
let user = dict["123"]
Update #1: General approach
Given an array of a given type Element, and a closure that determine the key of an Element, the following generic function will generate a Dictionary of type [Key:Element]
func createIndex<Key, Element>(elms:[Element], extractKey:(Element) -> Key) -> [Key:Element] where Key : Hashable {
return elms.reduce([Key:Element]()) { (dict, elm) -> [Key:Element] in
var dict = dict
dict[extractKey(elm)] = elm
return dict
}
}
Example
let users: [User] = [
User(id: "a0", firstName: "a1", lastName: "a2"),
User(id: "b0", firstName: "b1", lastName: "b2"),
User(id: "c0", firstName: "c1", lastName: "c2")
]
let dict = createIndex(elms: users) { $0.id }
// ["b0": {id "b0", firstName "b1", lastName "b2"}, "c0": {id "c0", firstName "c1", lastName "c2"}, "a0": {id "a0", firstName "a1", lastName "a2"}]
Update #2
As noted by Martin R the reduce will create a new dictionary for each iteration of the related closure. This could lead to huge memory consumption.
Here's another version of the createIndex function where the space requirement is O(n) where n is the length of elms.
func createIndex<Key, Element>(elms:[Element], extractKey:(Element) -> Key) -> [Key:Element] where Key : Hashable {
var dict = [Key:Element]()
for elm in elms {
dict[extractKey(elm)] = elm
}
return dict
}
let pills = ["12", "34", "45", "67"]
let kk = Dictionary(uniqueKeysWithValues: pills.map{ ($0, "number") })
["12": "number", "67": "number", "34": "number", "45": "number"]
swift5 swift4
The following converts an array to a dictionary.
let firstArray = [2,3,4,5,5]
let dict = Dictionary(firstArray.map { ($0, 1) } , uniquingKeysWith: +)
Swift 5
extension Array {
func toDictionary() -> [Int: Element] {
self.enumerated().reduce(into: [Int: Element]()) { $0[$1.offset] = $1.element }
}
}
This extension works for all sequences (including arrays) and lets you select both key and value:
extension Sequence {
public func toDictionary<K: Hashable, V>(_ selector: (Iterator.Element) throws -> (K, V)?) rethrows -> [K: V] {
var dict = [K: V]()
for element in self {
if let (key, value) = try selector(element) {
dict[key] = value
}
}
return dict
}
}
Example:
let nameLookup = persons.toDictionary{($0.name, $0)}
Just do it simply,
let items = URLComponents(string: "https://im.qq.com?q=13&id=23")!.queryItems!
var dic = [String: Any?]()
items.foreach {
dic[$0.name] = $0.value
}
reduce is not very suitable,
let dic: [String: Any?] = items.reduce([:]) { (result: [String: Any?], item: URLQueryItem) -> [String: Any?] in
var r = result
r[item.name] = item.value // will create an copy of result!!!!!!
return r
}
As i understand from you're question you would like to convert to Array to Dictionary.
In my case i create extension for the Array and keys for the dictionary will be indexes of the Array.
Example:
var intArray = [2, 3, 5, 3, 2, 1]
extension Array where Element: Any {
var toDictionary: [Int:Element] {
var dictionary: [Int:Element] = [:]
for (index, element) in enumerate() {
dictionary[index] = element
}
return dictionary
}
}
let dic = intArray.toDictionary
Compatible with Swift 5 Standard Library (Xcode 10.2+ , iOS 12.2).
Here's an example of usage of an initializer init(uniqueKeysWithValues:)
The input let array: [String] = Locale.isoRegionCodes is an array of ISO31661-2 codes represented by a string.
let countryCodeAndName: [String: String] = Dictionary(uniqueKeysWithValues: Locale.isoRegionCodes.map { ($0, Locale.current.localizedString(forRegionCode: $0) ?? "")} )
Returned dictionary, will list all regions with ISO31661-2 code as a key and a localized region name as a value.
Output:
...
"PL":"Poland"
"DE":"Germany"
"FR":"France"
"ES":"Spain"
...
Example 2:
let dictionary: [String: String] = Dictionary(uniqueKeysWithValues: [ ("key1", "value1"), ("key2", "value2")] )
Output:
["key1": "value1", "key2": "value2"]
Important:
Precondition: The sequence must not have duplicate keys.
Code below will crash an app:
let digitWords = ["one", "two", "three", "four", "five", "five"]
let wordToValue = Dictionary(uniqueKeysWithValues: zip(digitWords, 1...6))
with:
Fatal error: Duplicate values for key: 'five'
If you want to follow the pattern set out by map and reduce in swift you could do something nice and functional like this:
extension Array {
func keyBy<Key: Hashable>(_ keyFor: (Element) -> Key) -> [Key: Element] {
var ret = [Key: Element]()
for item in self{
ret[keyFor(item)] = item
}
return ret
}
}
Usage:
struct Dog {
let id: Int
}
let dogs = [Dog(id: 1), Dog(id: 2), Dog(id: 3), Dog(id: 4)]
let dogsById = dogs.keyBy({ $0.id })
// [4: Dog(id: 4), 1: Dog(id: 1), 3: Dog(id: 3), 2: Dog(id: 2)]
Swift way:
extension Sequence {
func toDictionary<Key: Hashable>(with selectKey: (Element) -> Key) -> [Key: Element] {
reduce(into: [:]) { $0[selectKey($1)] = $1 }
}
}
// let arr = [Person(id: 1, name: "Alan")]
// arr.toDictionary { $0.id }
// ==
// [1: Person(id: 1, name: "Alan")]
I'm trying to extend an array to return only objects at certain indexes. The map function seemed to be the best choice for me here.
extension Array {
func objectsAtIndexes(indexes: [Int]) -> [Element?]? {
let elements: [Element?] = indexes.map{ (idx) in
if idx < self.count {
return self[idx]
}
return nil
}.filter { $0 != nil }
return elements
}
}
let arr = ["1", "2", "3", "4", "5"]
let idx = [1,3,5]
let x = arr.objectsAtIndexes(idx) //returns: [{Some "2"}, {Some "4"}]
I'm getting a EXC_BAD_INSTRUCTION error when I try to cast the result to a string array:
let x = arr.objectsAtIndexes(idx) as? [String]
Is there any way I can return an array of non-optionals? I've tried to return [Element]? from the extension function.
This throws the same error.
The following code solves the problem for Swift2.1 using the flatmap function.
extension Array {
func objectsAtIndexes(indexes: [Int]) -> [Element] {
let elements: [Element] = indexes.map{ (idx) in
if idx < self.count {
return self[idx]
}
return nil
}.flatMap{ $0 }
return elements
}
}
I have array and need to reverse it without Array.reverse method, only with a for loop.
var names:[String] = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
Swift 3:
var names:[String] = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
var reversedNames : [String] = Array(names.reversed())
print(reversedNames) // ["Asus", "Lenovo", "Sony", "Microsoft", "Apple"]
Here is #Abhinav 's answer translated to Swift 2.2 :
var names: [String] = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
var reversedNames = [String]()
for arrayIndex in (names.count - 1).stride(through: 0, by: -1) {
reversedNames.append(names[arrayIndex])
}
Using this code shouldn't give you any errors or warnings about the use deprecated of C-style for-loops or the use of --.
Swift 3 - Current:
let names: [String] = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
var reversedNames = [String]()
for arrayIndex in stride(from: names.count - 1, through: 0, by: -1) {
reversedNames.append(names[arrayIndex])
}
Alternatively, you could loop through normally and subtract each time:
let names = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
let totalIndices = names.count - 1 // We get this value one time instead of once per iteration.
var reversedNames = [String]()
for arrayIndex in 0...totalIndices {
reversedNames.append(names[totalIndices - arrayIndex])
}
Do you really need a for loop? If not, you can use reduce.
I guess that this is the shortest way to achieve it without reversed() method (Swift 3.0.1):
["Apple", "Microsoft", "Sony", "Lenovo", "Asus"].reduce([],{ [$1] + $0 })
Only need to make (names.count/2) passes through the array. No need to declare temporary variable, when doing the swap...it's implicit.
var names:[String] = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
let count = names.count
for i in 0..<count/2 {
(names[i],names[count - i - 1]) = (names[count - i - 1],names[i])
}
// Yields: ["Asus", "Lenovo", "Sony", "Microsoft", "Apple"]
There's also stride to generate a reversed index:
let names = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
var reversed = [String]()
for index in (names.count - 1).stride(to: -1, by: -1) {
reversed.append(names[index])
}
It also works well with map:
let reversed = (names.count - 1).stride(to: -1, by: -1).map { names[$0] }
Note: stride starts its index at 1, not at 0, contrary to other Swift sequences.
However, to anyone reading this in the future: use .reverse() instead to actually reverse an array, it's the intended way.
var names:[String] = [ "A", "B", "C", "D", "E","F","G"]
var c = names.count - 1
var i = 0
while i < c {
swap(&names[i++],&names[c--])
}
Cristik
while i < c {
swap(&names[i],&names[c]
i += 1
c -= 1
}
Here you go:
var names:[String] = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
var reversedNames = [String]()
for var arrayIndex = names.count - 1 ; arrayIndex >= 0 ; arrayIndex-- {
reversedNames.append(names[arrayIndex])
}
Ignoring checks for emptiness..
var names:[String] = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
var reversedNames = [String]()
for name in names {
reversedNames.insert((name), at:0)
}
print(reversedNames)
Here is the most simpler way.
let names:[String] = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
var reversedNames = [String]()
for name in names {
reversedNames.insert(name, at: 0)
}
Edited as generic
// Swap the first index with the last index.
// [1, 2, 3, 4, 5] -> pointer on one = array[0] and two = array.count - 1
// After first swap+loop increase the pointer one and decrease pointer two until
// conditional is not true.
func reverse<T>(with array: [T]) -> [T] {
var array = array
var first = 0
var last = array.count - 1
while first < last {
array.swapAt(first, last)
first += 1
last -= 1
}
return array
}
input-> [1, 2, 3, 4, 5] output ->[5, 4, 3, 2, 1]
input-> ["a", "b", "c", "d"] output->["d", "c", "b", "a"]
// Or a shorter version divide and conquer
func reversed<T>(with arr: [T]) -> [T] {
var arr = arr
(0..<arr.count / 2).forEach { i in
arr.swapAt(i, arr.count - i - 1)
}
return arr
}
The most efficient way is to swap the items at start- and endIndex and move the indices bidirectional to the middle. This is a generic version
extension Array {
mutating func upsideDown() {
if isEmpty { return }
var 👉 = startIndex
var 👈 = index(before: endIndex)
while 👉 < 👈 {
swapAt(👉, 👈)
formIndex(after: &👉)
formIndex(before: &👈)
}
}
}
Like this, maybe:
names = names.enumerate().map() { ($0.index, $0.element) }.sort() { $0.0 > $1.0 }.map() { $0.1 }
Oh, wait.. I have to use for loop, right? Then like this probably:
for (index, name) in names.enumerate().map({($0.index, $0.element)}).sort({$0.0 > $1.0}).map({$0.1}).enumerate() {
names[index] = name
}
Swift 5:
let names: [String] = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
var reversenames: [String] = []
let count = names.count
for index in 0..<count {
reversenames.insert(names[count-index-1], at: index)
}
print(reversenames)
This will work with any sized array.
import Cocoa
var names:[String] = [ "A", "B", "C", "D", "E","F"]
var c = names.count - 1
for i in 0...(c/2-1) { swap(&names[i],&names[c-i]) }
print(names)
Here is how I did it and there is no warning for Swift 3
let names = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
var reversedNames = [String]()
for name in names.enumerate() {
let newIndex = names.count - 1 - name.index
reversedNames.append(names[newIndex])
}
or just simply
reversedNames = names.reverse()
Here the code for swift 3
let array = ["IOS A", "IOS B", "IOS C"]
for item in array.reversed() {
print("Found \(item)")
}
func reverse(array: inout [String]) {
if array.isEmpty { return }
var f = array.startIndex
var l = array.index(before: array.endIndex)
while f < l {
swap(array: &array, f, l)
array.formIndex(after: &f)
array.formIndex(before: &l)
}
}
private func swap( array: inout [String], _ i: Int, _ j: Int) {
guard i != j else { return }
let tmp = array[i]
array[i] = array[j]
array[j] = tmp
}
Or you can write extension of course
var rArray : [Int] = [2,5,6,8,3,8,9,10]
var ReArray = [Int]()
var a : Int = 1
func reversed (_ array: [Int]) -> [Int] {
for i in array {
ReArray.append(array[array.count-a])
a += 1
}
rArray = ReArray
return rArray
}
reversed(rArray)
print(rArray)
var arr = [1, 2, 3, 4, 5] // Array we want to reverse
var reverse: [Int]! // Array where we store reversed values
reverse = arr
for i in 0...(arr.count - 1) {
reverse[i] = arr.last! // Adding last value of original array at reverse[0]
arr.removeLast() // removing last value & repeating above step.
}
print("Reverse : \(reverse!)")
A more simple way :)
Recently I had an interview and I was asked this question, how to reverse an array without using reversed(). Here is my solution below:
func reverseArray( givenArray:inout [Int]) -> [Int] {
var reversedArray = [Int]()
while givenArray.count > 0 {
reversedArray.append(givenArray.removeLast())
}
return reversedArray
}
var array = [1,2,3,4,5,6,7]
var reversed = reverseArray(givenArray: &array)
First, need to find the middle of array. This method is faster than the linear time O(n) and slower than the constant time O(1) complexity.
func reverse<T>(items: [T]) -> [T] {
var reversed = items
let count = items.count
let middle = count / 2
for i in stride(from: 0, to: middle, by: 1) {
let first = items[i]
let last = items[count - 1 - i]
reversed[i] = last
reversed[count - 1 - i] = first
}
return reversed
}
Do it like this for reversed sorting.
let unsortedArray: [String] = ["X", "B", "M", "P", "Z"]
// reverse sorting
let reversedArray = unsortedArray.sorted() {$0 > $1}
print(reversedArray) // ["Z", "X", "P", "M", "B"]
I like simple codes.
var names:[String] = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
var reversedNames = [""]
for name in names {
reversedNames.insert(name, at: 0)
}
print(reversedNames)
var names = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]
// 'while' loop
var index = 0
let totalIndices = names.count - 1
while index < names.count / 2 {
names.swapAt(index, totalIndices-index)
index += 1
}
// 'for' loop
for index in 0..<names.count/2 {
names.swapAt(index, names.count-index-1)
}
// output: "["Asus", "Lenovo", "Sony", "Microsoft", "Apple"]"
You can use the swift3 document:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: >)
// reversedNames is equal to:
// ["Ewa", "Daniella", "Chris", "Barry", "Alex"]