skip to Main Content

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?

3

Answers


  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")
    
       }
    }
    
    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
  3. 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)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search