Search code examples
goslice

Insert a value in a slice at a given index


Given

array1 := []int{1, 3, 4, 5}
array2 := []int{2, 4, 6, 8}

I want to insert array2[2] i.e 6 at array1[1] i.e before 3 so that array1 becomes a slice of {1, 6, 3, 4, 5}. How can I do it?

Most the techniques I read online involve using the : operator but results in remaining elements being inserted as well. How can I append single values at an index in a slice?


Solution

  • Simple, efficient and logical way:

    1. Make sure array1 has enough capacity (length) to accomodate the new, insertable element. To do that, append a single element using the builting append() (doesn't matter what that is, it'll get overwritten).
    2. To insert an element, existing elements must be shifted (copied over to 1 index higher) to make room for that element, e.g. using the builtin copy() (elements you want to insert before).
    3. Set the element at the proper index, using a single assignment.

    In code:

    array1 := []int{1, 3, 4, 5}
    array2 := []int{2, 4, 6, 8}
    
    array1 = append(array1, 0)   // Step 1
    copy(array1[2:], array1[1:]) // Step 2
    array1[1] = array2[2]        // Step 3
    
    fmt.Println(array1)
    

    Output (try it on the Go Playground):

    [1 6 3 4 5]
    

    Optimization in special cases

    Note that in some special cases (when the slice element is big, like a big struct), it may be faster to append the last element, and then it's enough to copy 1 less elements (because the appended last element is right where it needs to be).

    This is how it looks like:

    last := len(array1) - 1
    array1 = append(array1, array1[last]) // Step 1
    copy(array1[2:], array1[1:last])      // Step 2
    array1[1] = array2[2]                 // Step 3
    

    This will result in the same slice. Try this one on the Go Playground.