How do I insert an item repeatedly between every two elements of an array?
Here is the original answer converted to Swift 3/4
let items = [1, 2, 3]
let sep = 0
let newItems = Array(items.map { [$0] }.joined(separator: [sep]))
print(newItems) // [1, 0, 2, 0, 3]
converted to swift 5
extension Array {
func insert(separator: Element) -> [Element] {
(0 ..< 2 * count - 1).map { $0 % 2 == 0 ? self[$0/2] : separator }
}
}
(Note: The answer has been updated for Swift 3 and later with the help of Brandon's answer and ober's answer).
This does the trick:
let items = [1, 2, 3]
let sep = 0
let newItems = Array(items.map { [$0] }.joined(separator: [sep]))
print(newItems) // [1, 0, 2, 0, 3]
items.map { [ $0 ] }
creates an array of single-element arrays, and joined(separator: [sep])
then interposes the separator and concatenates
the elements. The result is a JoinedSequence
from which we can create an Array
.
As it turns out (benchmarks below) it is quite expensive to create many temporary arrays. This can be avoided by using “single-element collections”:
let newItems = Array(items.map(CollectionOfOne.init).joined(separator: CollectionOfOne(sep)))
Another possible solution is
let newItems = (0 ..< 2 * items.count - 1).map { $0 % 2 == 0 ? items[$0/2] : sep }
which maps even indices to the corresponding element of items
,
and odd indices to the separator. This turns out to be the fastest solution for large arrays.
Benchmark: With items
containing 1,000,000 elements, compiled in Release mode on a 2.3 GHz Intel Core i7 MacBook Pro, I measured the following approximate execution times:
First method (
map
+joined
with arrays): 0.28 seconds.Second method (
map
+joined
withCollectionOfOne
): 0.035 seconds.Third method (using only
map
): 0.015 seconds.