29

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"]
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Milos Mandic
  • 1,046
  • 2
  • 13
  • 19
  • 12
    Why not use `reverse`? – Eric Aya Nov 01 '15 at 14:55
  • Use the same basic logic you would in any language, E.g. [C# Reverse an array without using reverse method of array](http://stackoverflow.com/questions/6088287/reverse-an-array-without-using-reverse-method-of-array) – Alex K. Nov 01 '15 at 14:57
  • 3
    @AlexK. The point is that there's already an efficient method in the Swift stdlib to do that. – Eric Aya Nov 01 '15 at 14:58
  • 12
    @EricD. Yea but the OP knows that; this is likely a comp sci assigment – Alex K. Nov 01 '15 at 14:59
  • I'd like an example of reverse implemented in a functional way, without mutating anything, e.g. similar to the traditional Lisp recursive reverse function. – Jean-Denis Muys Aug 24 '16 at 14:13
  • I’m voting to close this question because [the official algorithm](https://github.com/apple/swift/blob/main/stdlib/public/core/Reverse.swift) is open source. `reverse` is not special. Just look up whatever you need in the repo. –  Nov 27 '22 at 12:02

26 Answers26

29

Swift 3:

var names:[String] = ["Apple", "Microsoft", "Sony", "Lenovo", "Asus"]

var reversedNames : [String] = Array(names.reversed())

print(reversedNames)  // ["Asus", "Lenovo", "Sony", "Microsoft", "Apple"]
SpaceX
  • 2,814
  • 2
  • 42
  • 68
22

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])
}
ZGski
  • 2,398
  • 1
  • 21
  • 34
  • No warnings but bad code. You can avoid `arradIndex` and `_` with `for arrayIndex in (names.count - 1).stride(through: 0, by: -1)`. – Sulthan May 05 '16 at 18:09
  • Thanks @Sulthan! I've edited my answer reflect your much better solution. – ZGski May 05 '16 at 18:19
  • 2
    by the way, you could also mix it up with a `map` into `let reversedNames = (names.count - 1).stride(through: 0, by: -1).map { names[$0] }`. That solution is actually in [Eric's answer](http://stackoverflow.com/a/33463720/669586). – Sulthan May 05 '16 at 18:27
18

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 })
Ronan Boiteau
  • 9,608
  • 6
  • 34
  • 56
brunobasas
  • 383
  • 2
  • 14
6

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"]
Mike Chirico
  • 3,381
  • 1
  • 23
  • 20
4

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.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
  • 2
    I would use `stride(through: 0, by: -1)`. – Sulthan May 05 '16 at 18:30
  • To anyone reading this in the present (May '16, Xcode 7.3, Swift 2.2): .reverse() creates an ReverseRandomAccessCollection> which is not the same as an array; you cannot, for instance, add elements to it. – green_knight Jun 01 '16 at 20:27
  • @green_knight Yes and no. Yes, it does by default. No, *it's not a problem* because you can either force the type to array like `let result:[String] = names.reverse()` or use the array initializer like `let result = Array(names.reverse())`. – Eric Aya Jun 01 '16 at 20:31
  • Thanks. For me it _was_ a problem, because the documentation lags behind the implementation (it states that reverse() will return a reversed array, which it no longer does, though it has in the past), and casting to an array failed. That pretty much leaves one stranded. – green_knight Jun 02 '16 at 06:58
  • 1
    @milos-mandic Hey there. Could you please make up your mind and stop changing the accepted answer? Thanks! ;) – Eric Aya Jul 20 '16 at 13:26
  • 1
    @EricD honestly, I think your answer should be accepted over mine. – ZGski Jul 20 '16 at 14:39
4
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
  
}
user3441734
  • 16,722
  • 2
  • 40
  • 59
  • This no longer works, as the prefix and postfix incrementing/decrementing operators are no longer part of the Swift programming language. – Cristik Jul 04 '21 at 04:57
  • The new code snipped doesn't behave like the original one, there the post-increment and post-decrement operations were taking place after the swap, while in the new code they happen before the swap. And I think this make the code miss swapping the first element with the last. – Cristik Jul 05 '21 at 14:26
3

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])
}
Abhinav
  • 37,684
  • 43
  • 191
  • 309
  • 1
    I got a warning that 'C-style for statement is depreciated and will be removed in future' :( – senty Apr 22 '16 at 02:07
  • Is this still valid? @Abhinav – Lukesivi May 05 '16 at 11:48
  • @senty I've taken the liberty of translating and updating the accepted answer to Swift 2.2 as to clear any warnings within Xcode. [My Answer](http://stackoverflow.com/a/37057200/4577897). – ZGski May 05 '16 at 18:02
  • 1
    This no longer works, Swift has removed support for the postfix decrementing operators. – Cristik Jul 04 '21 at 04:59
3

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)
achinthaishane
  • 77
  • 1
  • 2
  • 9
Pilkie
  • 31
  • 3
2

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: &)
        }
    }
}
vadian
  • 274,689
  • 30
  • 353
  • 361
2

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)
}
Muhammad Khan
  • 284
  • 1
  • 3
  • 12
2

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
     }
Israel Manzo
  • 217
  • 3
  • 6
2

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)
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Saikiran Komirishetty
  • 6,525
  • 1
  • 29
  • 36
1

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
}
0x416e746f6e
  • 9,872
  • 5
  • 40
  • 68
0

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)
Simon O'Doherty
  • 9,259
  • 3
  • 26
  • 54
0

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()
Pavle Mijatovic
  • 773
  • 10
  • 6
0

Here the code for swift 3

let array = ["IOS A", "IOS B", "IOS C"]
    for item in array.reversed() {
    print("Found \(item)")
    }
Inder_iOS
  • 1,636
  • 1
  • 12
  • 20
  • 3
    The question is very specific about NOT using reverse/reversed. It's even mentioned in the comments under the question. When OP asked this, *everybody* suggested using reverse/reversed but OP needed something else. – Eric Aya Apr 13 '17 at 14:45
  • @ Eric Aya: I came here for this answer. This is such a classic question so I think many different approaches should be allowed. – Sentry.co Apr 24 '17 at 11:12
0
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

0
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)
Anh Pham
  • 2,108
  • 9
  • 18
  • 29
0
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 :)

Sapphire_Brick
  • 1,560
  • 12
  • 26
Mayank Neema
  • 1
  • 1
  • 2
0

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)
Arafin Russell
  • 1,487
  • 1
  • 18
  • 37
0

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
}
Kuvonchbek Yakubov
  • 558
  • 1
  • 6
  • 16
0

There are so many answers, Here in swift 5 by using generic method to reverse any type of array: modified from @tomeriko 's solution

func reverseArray<Element:Equatable>(input : [Element])-> [Element]{
   var count = input.count
   var result_ = input
   for index in 0..<input.count{
      result_.insert(input[count-index-1], at: index)
      result_.removeLast()
    }
   return result_
 }
 print(reverseArray(input: [1,2,3,4,5,6]))
 print(reverseArray(input: ["1","2","3","4"]))

output:

[6, 5, 4, 3, 2, 1]

["4", "3", "2", "1"]

-1

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"]
Divyanshu Kumar
  • 1,272
  • 15
  • 15
  • 2
    This doesn't answer the question because it reverse sorts the array, it doesn't reverse the original order as OP is asking. – Eric Aya Nov 06 '18 at 10:28
  • @Moritz you are right, but there are many newbies out there who will find this in search of reverse sorting, for their sake i have written this solution, and i have clearly mentioned "for reversed sorting". – Divyanshu Kumar Nov 12 '18 at 09:46
-1

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)
-1
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"]"
Obyadur
  • 34
  • 1
  • 5
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – abdo Salm Sep 28 '22 at 17:44
-2

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"]
bfontaine
  • 18,169
  • 13
  • 73
  • 107
Paresh Hirpara
  • 487
  • 3
  • 10