Repeating array in Swift

You can create a 2D array and then use flatMap to turn it into a 1D array:

let array = [[Int]](repeating: [1,2,3], count: 3).flatMap{$0}

If you want to have a general way of doing this, here's an extension that adds an init method and a repeating method that takes an array which makes this a bit cleaner:

extension Array {
  init(repeating: [Element], count: Int) {
    self.init([[Element]](repeating: repeating, count: count).flatMap{$0})
  }

  func repeated(count: Int) -> [Element] {
    return [Element](repeating: self, count: count)
  }
}

let array = [1,2,3].repeated(count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]

Note that with the new initializer you can get an ambiguous method call if you use it without providing the expected type:

let array = Array(repeating: [1,2,3], count: 3) // Error: Ambiguous use of ‛init(repeating:count:)‛

Use instead:

let array = [Int](repeating: [1,2,3], count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]

or

let array:[Int] = Array(repeating: [1,2,3], count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]

This ambiguity can be avoided if you change the method signature to init(repeatingContentsOf: [Element], count: Int) or similar.


You can use modulo operations for index calculations of your base collection and functional programming for this:

let base = [1, 2, 3]
let n = 3 //number of repetitions
let r = (0..<(n*base.count)).map{base[$0%base.count]}

You can create a custom overload for the * operator, which accepts an array on the left and an integer on the right side.

func * <T>(left: [T], right: Int) -> [T] {
    return (0..<(right*left.count)).map{left[$0%left.count]}
}

You can then use your function just like in python:

[1, 2, 3] * 3
// will evaluate to [1, 2, 3, 1, 2, 3, 1, 2, 3]

With Swift 5, you can create an Array extension method in order to repeat the elements of the given array into a new array. The Playground sample code below shows a possible implementation for this method:

extension Array {

    func repeated(count: Int) -> Array<Element> {
        assert(count > 0, "count must be greater than 0")

        var result = self
        for _ in 0 ..< count - 1 {
            result += self
        }

        return result
    }

}

let array = [20, 11, 87]
let newArray = array.repeated(count: 3)
print(newArray) // prints: [20, 11, 87, 20, 11, 87, 20, 11, 87]

If needed, you can also create an infix operator to perform this operation:

infix operator **

extension Array {

    func repeated(count: Int) -> Array<Element> {
        assert(count > 0, "count must be greater than 0")

        var result = self
        for _ in 0 ..< count - 1 {
            result += self
        }

        return result
    }

    static func **(lhs: Array<Element>, rhs: Int) -> Array<Element> {
        return lhs.repeated(count: rhs)
    }

}

let array = [20, 11, 87]
let newArray = array ** 3
print(newArray) // prints: [20, 11, 87, 20, 11, 87, 20, 11, 87]

Tags:

Arrays

Swift