Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I insert an item repeatedly between every two elements of an array?

Tags:

I have this code:

let items = [1, 2, 3] let sep = 0 

I want to insert sep between every two elements of items to get a result similar to this:

newItems = [1, 0, 2, 0, 3] 

Is there a concise way to do this through functional programming in Swift? Something similar to String.join(), but for arrays.

like image 235
hashemi Avatar asked Mar 30 '15 13:03

hashemi


People also ask

How do you add the first two elements of an array?

map the original array to another array by taking the first two elements of each subarray and concatenating them together, then building a new subarray by adding the rest of the elements (which we get with the rest parameter during the array destructuring) to a new array that contains the joined string.


2 Answers

(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 with CollectionOfOne): 0.035 seconds.

  • Third method (using only map): 0.015 seconds.

like image 82
Martin R Avatar answered Oct 01 '22 14:10

Martin R


converted to swift 5

extension Array {    func insert(separator: Element) -> [Element] {     (0 ..< 2 * count - 1).map { $0 % 2 == 0 ? self[$0/2] : separator }   } } 
like image 32
ober Avatar answered Oct 01 '22 15:10

ober