How to reverse array in Swift without using ".reverse()"? - arrays

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"]

Related

Swift inputing characters and strings into a dictionary

How would I go about Writing a function that takes in an array of strings and outputs a dictionary with the first character of each string as a key and the remaining as objects?
Writing this piece of code for you without seeing any trials from your side, just because you are new on StackOverflow. And I'm seeing the message from StackOverflow that "Corey Townsend is a new contributor. Be nice..."
So I'm just being nice for you as a welcome and here is your code.
let arr = ["car", "cat", "dog", "ball", "flower", "notebook", "fire"]
func createDictionaryFromArrayAsCoreyWants(arr:[String]) -> [String:String] {
var dict:[String:String] = [:]
arr.forEach({ (word:String) in
let strKey = String(word.prefix(1))
let startIndex: String.Index = word.index(word.startIndex, offsetBy: 1)
let strValue = String(word[startIndex..<word.endIndex])
dict[strKey] = strValue
print(strKey + " : " + strValue)
})
return dict
}
let d = createDictionaryFromArrayAsCoreyWants(arr: arr)
print(d)
Addition
Just saw a comment on another answer by 'Alex Bailer' so adding one more function for you. Enjoy...
func createDictionaryFromArrayAsCoreyWants(arr:[String]) -> [String:[String]] {
var dict:[String:[String]] = [:]
arr.forEach({ (word:String) in
let strKey = String(word.prefix(1))
let startIndex: String.Index = word.index(word.startIndex, offsetBy: 1)
let strValue = String(word[startIndex..<word.endIndex])
if let a = dict[strKey] {
dict[strKey] = a + [strValue]
} else {
dict[strKey] = [strValue]
}
print(strKey + " : " + strValue)
})
return dict
}
let d = createDictionaryFromArrayAsCoreyWants(arr: arr)
print(d)
Output:
["d": ["og"], "n": ["otebook"], "b": ["all"], "c": ["ar", "at"], "f": ["lower", "ire"]]
Is this what are you looking for?
let d = Dictionary(grouping: array, by: {$0.prefix(1)})
with array:
let array = ["car", "cat", "dog", "ball", "flower", "notebok", "fire"]
It prints:
["b": ["ball"], "f": ["flower", "fire"], "d": ["dog"], "c": ["car", "cat"], "n": ["notebok"]]
And then, remove the first letter from values:
for key in d.keys {
let values = d[key]
let start = String.Index(encodedOffset: 1)
d[key] = values?.compactMap({ String($0[start...]) })
}
Output:
["f": ["lower", "ire"], "d": ["og"], "b": ["all"], "c": ["ar", "at"], "n": ["otebok"]]

Swift: Remove repeated Index and create a new dictionary with reversed index and value

I have a dictionary with two Int’s A:B, and I want create a new dictionary that includes B as an index (with no repetition) and A as a value (only for repeated B’s):
var myDict : [Int:Int] = [12:2345, 14:2345, 99:1111, 67:1111, 77:7657, 132:3345, 199:6778]
Desired output:
var newDict: [Int:[Int]] = [2345: [ 12 , 14 ] , 1111: [ 99 , 67] ]
Note: the original dictionary contains over a thousand entries.
You loop through the first dict by enumerating it, that way you can switch the values in to the new dict
var newDict: [Int:[Int]] = [:]
let myDict : [Int:Int] = [12:2345, 14:2345, 99:1111, 67:1111, 77:7657, 132:3345, 199:6778]
for values in myDict.enumerated() {
var newValue = newDict[values.element.value] ?? []
newValue.append(values.element.key)
newDict[values.element.value] = newValue
}
newDict = newDict.filter { (key, value) -> Bool in
value.count > 1
}
Here is the power of swift:
let newDict = Dictionary(grouping: myDict, by: {$0.value}).filter({$0.value.count > 1}).mapValues({$0.map({$0.key})})
print(newDict)
Output: [1111: [67, 99], 2345: [12, 14]]
Please use this code:
var myDict: [Int:Int] = [12:2345, 14:2345, 99:1111, 67:1111, 77:7657, 132:3345, 199:6778]
let values = myDict.values
let tempValueSet = Set<Int>(values)
let uniqueValues = Array(tempValueSet)
var result = [Int: [Int]]()
for item in uniqueValues {
result[item] = myDict.allKeys(forValue: item)
}
print(result)
And this is Dictionary extension:
extension Dictionary where Value: Equatable {
func allKeys(forValue val: Value) -> [Key] {
return self.filter { $1 == val }.map { $0.0 }
}
}
Desired output:
[6778: [199], 1111: [99, 67], 7657: [77], 3345: [132], 2345: [12, 14]]
For more reference about this extension : https://stackoverflow.com/a/27218964/2284065
If you don't want to use extension then you can use this code too :
var myDict: [Int:Int] = [12:2345, 14:2345, 99:1111, 67:1111, 77:7657, 132:3345, 199:6778]
let values = myDict.values
let tempValueSet = Set<Int>(values)
let uniqueValues = Array(tempValueSet)
var result = [Int: [Int]]()
for item in uniqueValues {
result[item] = (myDict as NSDictionary).allKeys(for: item) as! [Int]
}
print(result)

how to combine two dictionary values as a key and value pair in swift

let arra = ["abc","def","abc","def"]
let arra2 = ["addr1","addr2","addr1","addr2"]
Expected Output
dic = ["abc":"addr1","addr1" , def: "addr2","addr2"]
Swift 4's new Dictionary initializer lets you do that kind of thing easily:
let arra = ["abc","def","abc","def"]
let arra2 = ["addr1","addr2","addr1","addr2"]
let dict = [String:[String]](zip(arra,arra2.map{[$0]}),uniquingKeysWith:+)
print(dict) // ["abc": ["addr1", "addr1"], "def": ["addr2", "addr2"]]
[EDIT] Swift 3 equivalent :
var dict : [String:[String]] = [:]
zip(arra,arra2.map{[$0]}).forEach{ dict[$0] = (dict[$0] ?? []) + $1 }
There should be easier way but in general:
import UIKit
let keyArray = ["abc","def","abc","def"]
let valueArray = ["addr1","addr2","addr1","addr2"]
let setFromKeyArray = Set(keyArray)
var finalDict = [String: [String]]()
for index in 0..<keyArray.count {
if let _ = finalDict[keyArray[index]] {
finalDict[keyArray[index]]!.append(valueArray[index])
} else {
finalDict[keyArray[index]] = [valueArray[index]]
}
}
print(finalDict)
// output: ["abc": ["addr1", "addr1"], "def": ["addr2", "addr2"]]
Using zip(_:_:) and reduce(_:_:):
let array1 = ["abc", "def", "abc", "def"]
let array2 = ["addr1", "addr2", "addr1", "addr2"]
let dictionary = zip(array1, array2).reduce([String: String]()) {
var dictionary = $0
dictionary[$1.0] = $1.1
return dictionary
}
print(dictionary) // ["abc": "addr1", "def": "addr2"]
You can use like below :
let arra = ["abc","def","abc","def"]
let arra2 = ["addr1","addr2","addr1","addr2"]
var dictionary: [String: String] = [:]
dictionary.merge(zip(arra, arra2)) { (old, new) -> String in
return "\(old), \(new)"
}
print(dictionary)
Output :
["abc": "addr1, addr1", "def": "addr2, addr2"]
The best of Dennis and Kristijan and Alain.
let arra = ["abc", "def", "abc", "def"]
let arra2 = ["addr1", "addr2", "addr1", "addr2"]
let dict = zip(arra, arra2).reduce([String:[String]]()){
var d = $0
d[$1.0] = ($0[$1.0] ?? []) + [$1.1]
return d
}
print(dict) // ["def":Β ["addr2",Β "addr2"],Β "abc":Β ["addr1",Β "addr1"]]
Remember dictionary is unordered.

Use of unresolved identifier 'finalArray'?

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)

Swift: match two arrays into one array

I have two arrays
array1 = ["Fri","Sat","Sun"]
array2 = ["5","6","7"]
Now I want to create a newArray: ["Fri5", "Sat6", "Sun7"]. How to make it? Thanks in advance.
For a functional approach, use zip and map:
let array1 = ["Fri","Sat","Sun"]
let array2 = ["5","6","7"]
let result = zip(array1, array2).map { $0 + $1 }
print(result)
Output:
["Fri5", "Sat6", "Sun7"]
zip creates a sequence of tuples [("Fri", "5"), ("Sat", "6"), ("Sun", "7")] and map then creates the final array by taking each tuple and combining the two Strings into a single String.
You can also try with this:
var array1 = ["Fri","Sat","Sun"]
var array2 = ["5","6","7"]
var array3 = array1.map{ $0 + (array2[array1.indexOf($0)!]) } // ["Fri5", "Sat6", "Sun7"]
With Swift 5 you can use one of the five following Playground sample codes in order to solve your problem.
#1. Using sequence(state:next:)
let array0 = ["Fri", "Sat", "Sun"]
let array1 = ["5", "6", "7"]
let unfoldSequence = sequence(state: (array0.makeIterator(), array1.makeIterator()), next: { (iterators) -> String? in
guard let string0 = iterators.0.next(), let string1 = iterators.1.next() else { return nil }
return string0 + string1
})
let array = Array(unfoldSequence)
print(array) // prints: ["Fri5", "Sat6", "Sun7"]
#2. Using zip(_:_:) and map(_:)
let array0 = ["Fri", "Sat", "Sun"]
let array1 = ["5", "6", "7"]
let array = zip(array0, array1).map({ $0 + $1 })
print(array) // prints: ["Fri5", "Sat6", "Sun7"]
#3. Using zip(_:_:) and reduce(into:_:)
let array0 = ["Fri", "Sat", "Sun"]
let array1 = ["5", "6", "7"]
let array = zip(array0, array1).reduce(into: [String](), { (result, tuple) in
result.append(tuple.0 + tuple.1)
})
print(array) // prints: ["Fri5", "Sat6", "Sun7"]
#4. Using AnyIterator
let array0 = ["Fri", "Sat", "Sun"]
let array1 = ["5", "6", "7"]
var iterator0 = array0.makeIterator()
var iterator1 = array1.makeIterator()
let anyIterator = AnyIterator<String> {
guard let string0 = iterator0.next(), let string1 = iterator1.next() else { return nil }
return string0 + string1
}
let array = Array(anyIterator)
print(array) // prints: ["Fri5", "Sat6", "Sun7"]
#5. Creating an object that conforms to Sequence and IteratorProtocol protocols
struct StringArrayConcatenatingSequence: Sequence, IteratorProtocol {
let firstArray: [String]
let secondArray: [String]
private var index = 0
init(firstArray: [String], secondArray: [String]) {
self.firstArray = firstArray
self.secondArray = secondArray
}
mutating func next() -> String? {
guard index < Swift.min(firstArray.count, secondArray.count) else { return nil }
defer { index += 1 }
return firstArray[index] + secondArray[index]
}
}
let array0 = ["Fri", "Sat", "Sun"]
let array1 = ["5", "6", "7"]
let sequence = StringArrayConcatenatingSequence(firstArray: array0, secondArray: array1)
let array = Array(sequence)
print(array) // prints: ["Fri5", "Sat6", "Sun7"]

Resources