Reputation: 96556
In Go you can insert a slice into the middle of another slice like this:
a = append(a[:i], append(b, a[i:]...)...)
However, as I understand it that will first append a[i:]
to b
by copying it to the end of b
(and potentially reallocating b
, and then copy that whole slice to a
, again potentially reallocating it.
This seems like there is an extra copy and allocation to what you really need. In C++ I'd do it something like this (I mean... without using insert
obviously).
// Reserve enough space in `a` for `a` and `b`.
a.reserve(a.size() + b.size());
// Move the second half of `a` to the end.
std::copy(a.begin() + i, a.end(), a.begin() + i + b.size());
// Copy `b` into the middle.
std::copy(b.begin(), b.end(), a.begin() + i);
Is there a similar way to do this in Go?
Upvotes: 2
Views: 214
Reputation: 120941
Here's a translation to Go assuming a slice of int:
// Reserve space for the combined length of the slices
c := make([]int, len(a)+len(b))
// Copy the first part of a to the beginning
copy(c, a[:i])
// Copy the last part of a to the end
copy(c[i+len(b):], a[i:])
// Copy b to the middle
copy(c[i:], b)
To take advantage of a
's capacity, do this:
if cap(a) < len(a)+len(b) {
// Not enough space, allocate new slice
c := make([]int, len(a)+len(b))
// Copy the first part of a to the beginning
copy(c, a[:i])
// Copy the last part of a to the end
copy(c[i+len(b):], a[i:])
a = c
} else {
// reslice to combined length
a = a[:len(a)+len(b)]
// copy the last part of a to the end
copy(a[i+len(b):], a[i:])
}
// copy b to the middle
copy(a[i:], b)
Upvotes: 6