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]