Array slicing selects a contiguous subrange from an array. A slice may be a view into the original storage, or it may be a new copied array.
You use it when an algorithm should operate on part of an array without manually passing start and end indices everywhere.
Problem
Given an array of length , create a slice from index up to but not including index :
where
Structure
A slice view usually stores:
- reference to the same backing array
- start offset
- length
For example:
and
The slice view points into the same storage rather than copying elements.
Algorithm
Create a slice view:
slice(A, l, r):
if l < 0 or r > length(A) or l > r:
error "invalid slice range"
S.base = A
S.start = l
S.length = r - l
return SRead from a slice:
get(S, i):
if i < 0 or i >= S.length:
error "index out of bounds"
return S.base[S.start + i]Example
Let
Create:
| slice index | base index | value |
|---|---|---|
| 0 | 1 | 3 |
| 1 | 2 | 5 |
| 2 | 3 | 1 |
Reading maps to:
Return .
Correctness
The slice range check ensures that and describe a valid contiguous subrange of the base array. The slice stores length , so every valid slice index satisfies . Mapping it to gives an index in the original range , so each slice access returns exactly the corresponding base-array element.
Complexity
| operation | view slice | copied slice |
|---|---|---|
| create slice | ||
| get | ||
| set |
Here:
A view slice uses:
extra space.
A copied slice uses:
extra space.
When to Use
Array slicing is appropriate when:
- an algorithm works on subranges
- copying would be unnecessary
- start and end indices make code noisy
- recursive or divide-and-conquer logic needs clean boundaries
Be careful with view slices when:
- mutating the slice may affect the original array
- a small slice keeps a large backing array alive
- concurrent code may observe shared storage
Implementation
class Slice:
def __init__(self, base, start, end):
if start < 0 or end > len(base) or start > end:
raise IndexError("invalid slice range")
self.base = base
self.start = start
self.length = end - start
def get(self, i):
if i < 0 or i >= self.length:
raise IndexError("index out of bounds")
return self.base[self.start + i]
def set(self, i, x):
if i < 0 or i >= self.length:
raise IndexError("index out of bounds")
self.base[self.start + i] = xtype Slice[T any] struct {
base []T
start int
size int
}
func NewSlice[T any](base []T, start, end int) (*Slice[T], bool) {
if start < 0 || end > len(base) || start > end {
return nil, false
}
return &Slice[T]{
base: base,
start: start,
size: end - start,
}, true
}
func (s *Slice[T]) Get(i int) (T, bool) {
var zero T
if i < 0 || i >= s.size {
return zero, false
}
return s.base[s.start+i], true
}
func (s *Slice[T]) Set(i int, x T) bool {
if i < 0 || i >= s.size {
return false
}
s.base[s.start+i] = x
return true
}