13

In Python I can create a repeating list like this:

>>> [1,2,3]*3
[1, 2, 3, 1, 2, 3, 1, 2, 3]

Is there a concise way to do this in Swift?

The best I can do is:

  1> var r = [Int]()
r: [Int] = 0 values
  2> for i in 1...3 { 
  3.     r += [1,2,3]
  4. }
  5> print(r)
[1, 2, 3, 1, 2, 3, 1, 2, 3]

4 Answers 4

37

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.

Sign up to request clarification or add additional context in comments.

2 Comments

You need to change the count parameter type to Int to use it as an index or coerce from Uint to Int self.init([Array](count: Int(count), repeatedValue: repeatedValues).flatMap{$0})
Ahh, yep it turns out that when I was testing it I was using slightly different code than I posted here. I changed it to better match the original init method.
7

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]

Comments

5

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]

1 Comment

Very cool! However, I'd like to lean away from implementing Python syntax in Swift. Probably not good for code readability.
0

Solution 1:

func multiplerArray(array: [Int], time: Int) -> [Int] {
    var result = [Int]()
    for _ in 0..<time {
        result += array
    }
    return result
}

Call this

print(multiplerArray([1,2,3], time: 3)) // [1, 2, 3, 1, 2, 3, 1, 2, 3]

Solution 2:

let arrays = Array(count:3, repeatedValue: [1,2,3])
// [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
var result = [Int]()
for array in arrays {
    result += array
}
print(result) //[1, 2, 3, 1, 2, 3, 1, 2, 3]

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.