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"]
6
  • 13
    Why not use reverse? Commented Nov 1, 2015 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 Commented Nov 1, 2015 at 14:57
  • 3
    @AlexK. The point is that there's already an efficient method in the Swift stdlib to do that. Commented Nov 1, 2015 at 14:58
  • 14
    @EricD. Yea but the OP knows that; this is likely a comp sci assigment Commented Nov 1, 2015 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. Commented Aug 24, 2016 at 14:13

27 Answers 27

31

Swift 3:

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

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

print(reversedNames)  // ["Asus", "Lenovo", "Sony", "Microsoft", "Apple"]
Sign up to request clarification or add additional context in comments.

1 Comment

The quesiton specifically states that it wants a solution without using reverse(). reversed() is the same other than getting a new array instead of sorting the original.
23

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])
}

3 Comments

No warnings but bad code. You can avoid arradIndex and _ with for arrayIndex in (names.count - 1).stride(through: 0, by: -1).
Thanks @Sulthan! I've edited my answer reflect your much better solution.
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.
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 })

Comments

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

Comments

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.

6 Comments

I would use stride(through: 0, by: -1).
To anyone reading this in the present (May '16, Xcode 7.3, Swift 2.2): .reverse() creates an ReverseRandomAccessCollection<Array<String>> which is not the same as an array; you cannot, for instance, add elements to it.
@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()).
@milos-mandic Hey there. Could you please make up your mind and stop changing the accepted answer? Thanks! ;)
@EricD honestly, I think your answer should be accepted over mine.
|
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
  
}

2 Comments

This no longer works, as the prefix and postfix incrementing/decrementing operators are no longer part of the Swift programming language.
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.
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])
}

4 Comments

I got a warning that 'C-style for statement is depreciated and will be removed in future' :(
Is this still valid? @Abhinav
@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.
This no longer works, Swift has removed support for the postfix decrementing operators.
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)

Comments

3

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)

Comments

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
     }

1 Comment

func reversed<T>(with arr: [T]) -> [T] { var arr = arr (0..<arr.count / 2).forEach { arr.swapAt($0, arr.count - $0 - 1) } return arr }
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: &👈)
        }
    }
}

Comments

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
}

Comments

1

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)
}

1 Comment

Solution already given in stackoverflow.com/a/37400672 by Pilkie
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)

3 Comments

If I remember correctly, swap() cannot exchange an element with itself in Swift 2. That would happen here for an odd-sized array. Or did they fix that in Swift 2.1?
@MartinR fixed. Although it will have issues with 1 item array. Although you could skip the whole loop if names.count = 1.
meh.. not a great answer.
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()

Comments

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

Comments

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)

Comments

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 :)

Comments

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)

Comments

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
}

Comments

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

Comments

0

Reverse the array recursively.

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

func reverseRecursively<T>(start: Int, end: Int, array: inout [T]) {
    if start > end { return }
    
    let temp = array[start]
    array[start] = array[end]
    array[end] = temp

    reverseRecursively(start: start + 1, end: end - 1, array: &array)
}

reverseRecursively(start: 0, end: name.count - 1, array: &names)

print(names)
// output: "["Asus", "Lenovo", "Sony", "Microsoft", "Apple"]"

1 Comment

Using recursion will fail once the array contains enough elements.
-1

Here the code for swift 3

let array = ["IOS A", "IOS B", "IOS C"]
    for item in array.reversed() {
    print("Found \(item)")
    }

2 Comments

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: I came here for this answer. This is such a classic question so I think many different approaches should be allowed.
-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"]

2 Comments

This doesn't answer the question because it reverse sorts the array, it doesn't reverse the original order as OP is asking.
@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".
-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"]"

1 Comment

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

2 Comments

This doesn't answer the question, it sorts the array, it doesn't reverse it.
Please post answers relevant to the question.This answers sorts an array not reverses it.
-2

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.