1

There is an array

var  sampleArray = ["1","2","3","4","5","6","7","8","9","10"]

there are two elements "header " and "footer"

I want to add these two elements such way that after every 3rd index of original array these two are to be appended

Expected Output

sampleArray = ["1","2","3", "header","footer" ,"4","5","6","header","footer""7","8","9""header","footer",10]

I google through the same of the build in methods provided , I found below

insert(_:at:)

But its not serving my purpose, It looks an obvious problem, Is there anybody who created the function like this?

2
  • array of strings Commented Feb 4, 2021 at 9:15
  • I added the quote , thanks Commented Feb 4, 2021 at 9:18

3 Answers 3

1

Use new array to proper combine

var result: [String] = []
for index in 0..< sampleArray.count {
   result.append(sample[index])
   if (index+1) % 3 == 0 {
       result.append("header")
       result.append("footer")

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

2 Comments

looks fine, thanks , I am trying to create the extension of array now.
1

You can't just insert into the indices 3, 6, 9 etc, in that order, because after inserting at index 3, the next index to insert at changes (increases by the number of elements you inserted). The third time you insert, it's been shifted by twice the number of elements you inserted, and so on. If you take this into account, it's quite simple:

var sampleArray = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
let sectionLength = 3
let separator = ["header", "footer"]
for (count, i) in stride(from: sectionLength, to: sampleArray.endIndex, by: sectionLength).enumerated() {
    sampleArray.insert(contentsOf: separator, at: i + count * separator.count)
}

Alternative solution that creates a new array:

let result = sampleArray.enumerated().flatMap { index, element in
    index % 3 == 2 ? [element] + separator : [element]
}

The idea here is to flatMap certain elements to that element plus the separator, and other elements to themselves. separator should be added after 3, 6 and 9, which are at indices 2, 5, and 8 respectively. Their indices are all one less than a multiple of 3, hence index % 3 == 2.

Comments

1

The issue is that you are invalidating the indices of your collection when inserting new elements. From the docs

Calling this method may invalidate any existing indices for use with this collection.

The most simple solution when you need to insert or remove multiple elements is to iterate your collection indices in reverse order:


var  sampleArray = ["1","2","3","4","5","6","7","8","9","10"]

var insertions = ["header", "footer"]

for index in sampleArray.indices.dropFirst().reversed() where index.isMultiple(of: 3) {
    sampleArray.insert(contentsOf: insertions, at: index)
}

sampleArray   // ["1", "2", "3", "header", "footer", "4", "5", "6", "header", "footer", "7", "8", "9", "header", "footer", "10"]


If you would like to implement your own insert methods:

extension RangeReplaceableCollection {

    mutating func insert<C>(contentsOf newElements: C, every nth: Int) where C : Collection, Self.Element == C.Element, Index == Int {
        for index in indices.dropFirst().reversed() where index.isMultiple(of: nth) {
            insert(contentsOf: newElements, at: index)
        }
    }
    
    mutating func insert(_ newElement: Element, every nth: Int) where Index == Int {
        for index in indices.dropFirst().reversed() where index.isMultiple(of: nth) {
            insert(newElement, at: index)
        }
    }
}

Usage:

sampleArray.insert(contentsOf: insertions, every: 3)
// sampleArray.insert("header", every: 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.