core/slice
slice
Types
6Generic_Cmp
Generic_Cmp :: proc(lhs: rawptr, rhs: rawptr, user_data: rawptr) -> (Ordering)SourceMap_Entry
Map_Entry :: struct {}SourceMap_Entry_Info
Map_Entry_Info :: struct {}SourceOrdering
Ordering :: enum int {
Less = -1,
Equal = 0,
Greater = 1,
}SourcePermutation_Iterator
Permutation_Iterator :: struct {}SourceAn in-place permutation iterator.
Sort_Kind
Sort_Kind :: enum int {
Ordered = 0,
Less = 1,
Cmp = 2,
}SourceConstants
1ORD
ORD :: intrinsics.type_is_orderedSourceProcedures
113_sort_by_indices
_sort_by_indices :: proc(data: T, sorted: T, indices: []int)Source_stable_sort_general
_stable_sort_general :: proc(data: T, call: P, KIND: Sort_Kind)Sourceadvance_slices
advance_slices :: proc(slices: S, elems: int) -> (S)SourceRemoves the first n elements (elems) from a slice of slices, spanning inner slices and dropping empty ones.
If elems is out of bounds (more than the total) this will trigger a bounds check.
Example:
import "core:fmt"
import "core:slice"
advance_slices_example :: proc() {
slices := [][]byte {
{1, 2, 3, 4},
{5, 6, 7},
}
fmt.println(slice.advance_slices(slices, 4))
}Output:
[[5, 6, 7]]all_of
all_of :: proc(s: S, value: T) -> (bool)Sourceall_of_proc
all_of_proc :: proc(s: S, f: proc() -> (bool)) -> (bool)Sourceany_of
any_of :: proc(s: S, value: T) -> (bool)Sourceany_of_proc
any_of_proc :: proc(s: S, f: proc() -> (bool)) -> (bool)Sourceas_ptr
as_ptr :: proc(array: T) -> ([^]E)Sourcebinary_search
binary_search :: proc(array: A, key: T) -> (index: int, found: bool)SourceSearches the given slice for the given element. If the slice is not sorted, the returned index is unspecified and meaningless.
If the value is found then the returned int is the index of the matching element. If there are multiple matches, then any one of the matches could be returned.
If the value is not found then the returned int is the index where a matching element could be inserted while maintaining sorted order.
For slices of more complex types see: binary_search_by
Example:
/*
Looks up a series of four elements. The first is found, with a
uniquely determined position; the second and third are not
found; the fourth could match any position in `[1, 4]`.
*/
index: int
found: bool
s := []i32{0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55}
index, found = slice.binary_search(s, 13)
assert(index == 9 && found == true)
index, found = slice.binary_search(s, 4)
assert(index == 7 && found == false)
index, found = slice.binary_search(s, 100)
assert(index == 13 && found == false)
index, found = slice.binary_search(s, 1)
assert(index >= 1 && index <= 4 && found == true)binary_search_by
binary_search_by :: proc(array: A, key: K, f: proc() -> (Ordering)) -> (index: int, found: bool)SourceSearches the given slice for the given element. If the slice is not sorted, the returned index is unspecified and meaningless.
If the value is found then the returned int is the index of the matching element. If there are multiple matches, then any one of the matches could be returned.
If the value is not found then the returned int is the index where a matching element could be inserted while maintaining sorted order.
The array elements and key may be different types. This allows the filter procedure to compare keys against a slice of structs, one struct value at a time.
Returns:
- index: int
- found: bool
bitset_to_enum_slice_with_buffer
bitset_to_enum_slice_with_buffer :: proc(buf: []E, bs: T) -> (slice: []E)SourceTurn a bit_set[E] into a []E e.g.: sl := slice.bitset_to_enum_slice(flag_buf[:], bs)
bitset_to_enum_slice_with_make
bitset_to_enum_slice_with_make :: proc(bs: T, E: typeid, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (slice: []E)SourceTurn a bit_set[E] into a []E, allocates e.g.: sl := slice.bitset_to_enum_slice(bs)
bytes_from_ptr
bytes_from_ptr :: proc(ptr: rawptr, byte_count: int) -> ([]u8)SourceTurn a pointer and a length into a byte slice.
clone
clone :: proc(a: T, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> ([]E, runtime.Allocator_Error)Sourcecopies a slice into a new slice
clone_to_dynamic
clone_to_dynamic :: proc(a: T, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> ([dynamic]E, runtime.Allocator_Error)Sourcecopies slice into a new dynamic array
cmp
cmp :: proc(a: E, b: E) -> (Ordering)Sourcecmp_proc
cmp_proc :: proc(E: typeid) -> (proc() -> (Ordering))Sourceconcatenate
concatenate :: proc(a: []T, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (res: T, err: runtime.Allocator_Error)Sourcecontains
contains :: proc(array: T, value: E) -> (bool)Sourcecount
count :: proc(s: S, value: T) -> (n: int)Sourcecount_proc
count_proc :: proc(s: S, f: proc() -> (bool)) -> (n: int)Sourcedestroy_permutation_iterator
destroy_permutation_iterator :: proc(iter: Permutation_Iterator($T), allocator: mem.Allocator = context.allocator)SourceFree the state allocated by make_permutation_iterator.
Inputs:
- iter: The iterator created by
make_permutation_iterator. - allocator: The allocator used to create the iterator. (default is context.allocator)
dot_product
dot_product :: proc(a: S, b: S) -> (r: T, ok: bool)Sourceenum_slice_to_bitset
enum_slice_to_bitset :: proc(enums: []E, T: typeid) -> (bits: T)SourceTurn a []E into bit_set[E] e.g.: bs := slice.enum_slice_to_bitset(my_flag_slice, rl.ConfigFlags)
enumerated_array
enumerated_array :: proc(ptr: ^T) -> ([]intrinsics.type_elem_type(T))SourceConvert a pointer to an enumerated array to a slice of the element type
equal
equal :: proc(a: T, b: T) -> (bool)Sourcefill
fill :: proc(array: T, value: E)Sourcefilter
filter :: proc(s: S, f: proc() -> (bool), allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (res: S, err: runtime.Allocator_Error)Sourcefilter_reverse
filter_reverse :: proc(s: S, f: proc() -> (bool), allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (res: S, err: runtime.Allocator_Error)Sourcefirst
first :: proc(array: T) -> (E)Sourcefirst_ptr
first_ptr :: proc(array: T) -> (^E)Sourcefrom_ptr
from_ptr :: proc(ptr: ^T, count: int) -> ([]T)SourceTurn a pointer and a length into a slice.
get
get :: proc(array: T, index: int) -> (value: E, ok: bool)Sourceget_ptr
get_ptr :: proc(array: T, index: int) -> (value: ^E, ok: bool)Sourcehas_prefix
has_prefix :: proc(array: T, needle: T) -> (bool)Sourcehas_suffix
has_suffix :: proc(array: T, needle: T) -> (bool)Sourceinto_dynamic
into_dynamic :: proc(a: T) -> ([dynamic]E)SourceConverts slice into a dynamic array without cloning or allocating memory
is_empty
is_empty :: proc(a: T) -> (bool)Sourceis_sorted
is_sorted :: proc(array: T) -> (bool)Sourceis_sorted_by
is_sorted_by :: proc(array: T, less: proc(i: E, j: E) -> (bool)) -> (bool)Sourceis_sorted_by_cmp
is_sorted_by_cmp :: proc(array: T, cmp: proc(i: E, j: E) -> (Ordering)) -> (bool)Sourceis_sorted_by_key
is_sorted_by_key :: proc(array: T, key: proc() -> (K)) -> (bool)Sourceis_sorted_cmp
is_sorted_cmp :: proc(array: T, cmp: proc(i: E, j: E) -> (Ordering)) -> (bool)Sourcelast
last :: proc(array: T) -> (E)Sourcelast_ptr
last_ptr :: proc(array: T) -> (^E)Sourcelength
length :: proc(a: T) -> (int)Sourcelinear_search
linear_search :: proc(array: A, key: T) -> (index: int, found: bool)SourceSearches the given slice for the given element in O(n) time.
If you need a custom search condition, see linear_search_proc
Inputs:
- array: The slice to search in.
- key: The element to search for.
Returns:
- index: The index
i, such thatarray[i]is the first occurrence ofkeyinarray, or -1 ifkeyis not present inarray.
Example:
index: int
found: bool
a := []i32{10, 10, 10, 20}
index, found = linear_search_reverse(a, 10)
assert(index == 0 && found == true)
index, found = linear_search_reverse(a, 30)
assert(index == -1 && found == false)
// Note that `index == 1`, since it is relative to `a[2:]`
index, found = linear_search_reverse(a[2:], 20)
assert(index == 1 && found == true)linear_search_proc
linear_search_proc :: proc(array: A, f: proc() -> (bool)) -> (index: int, found: bool)SourceSearches the given slice for the first element satisfying predicate f in O(n) time.
Inputs:
- array: The slice to search in.
- f: The search condition.
Returns:
- index: The index
i, such thatarray[i]is the firstxinarrayfor whichf(x) == true, or -1 if suchxdoes not exist.
linear_search_reverse
linear_search_reverse :: proc(array: A, key: T) -> (index: int, found: bool)SourceSearches the given slice for the given element in O(n) time, starting from the slice end.
If you need a custom search condition, see linear_search_reverse_proc
Inputs:
- array: The slice to search in.
- key: The element to search for.
Returns:
- index: The index
i, such thatarray[i]is the last occurrence ofkeyinarray, or -1 ifkeyis not present inarray.
Example:
index: int
found: bool
a := []i32{10, 10, 10, 20}
index, found = linear_search_reverse(a, 20)
assert(index == 3 && found == true)
index, found = linear_search_reverse(a, 10)
assert(index == 2 && found == true)
index, found = linear_search_reverse(a, 30)
assert(index == -1 && found == false)
// Note that `index == 1`, since it is relative to `a[2:]`
index, found = linear_search_reverse(a[2:], 20)
assert(index == 1 && found == true)linear_search_reverse_proc
linear_search_reverse_proc :: proc(array: A, f: proc() -> (bool)) -> (index: int, found: bool)SourceSearches the given slice for the last element satisfying predicate f in O(n) time, starting from the slice end.
Inputs:
- array: The slice to search in.
- f: The search condition.
Returns:
- index: The index
i, such thatarray[i]is the lastxinarrayfor whichf(x) == true, or -1 if suchxdoes not exist.
make_permutation_iterator
make_permutation_iterator :: proc(slice: []T, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (iter: Permutation_Iterator(T), error: runtime.Allocator_Error)SourceMake an iterator to permute a slice in-place.
Allocates Using Provided Allocator
This procedure allocates some state to assist in permutation and does not make a copy of the underlying slice. If you want to permute a slice without altering the underlying data, use clone to create a copy, then permute that instead.
Inputs:
- slice: The slice to permute.
- allocator: (default is context.allocator)
Returns:
- iter: The iterator, to be passed to
permute. - error: An
Allocator_Error, if allocation failed.
map_entries
map_entries :: proc(m: M, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (entries: []Map_Entry(K, V), err: runtime.Allocator_Error)Sourcemap_entry_infos
map_entry_infos :: proc(m: M, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (entries: []Map_Entry_Info(K, V), err: runtime.Allocator_Error)Sourcemap_keys
map_keys :: proc(m: M, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (keys: []K, err: runtime.Allocator_Error)Sourcemap_values
map_values :: proc(m: M, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (values: []V, err: runtime.Allocator_Error)Sourcemapper
mapper :: proc(s: S, f: proc() -> (V), allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (r: []V, err: runtime.Allocator_Error)Sourcemax
max :: proc(s: S) -> (res: T, ok: bool)Sourcemax_index
max_index :: proc(s: S) -> (max_index: int, ok: bool)SourceFind the index of the (first) maximum element in a slice.
min
min :: proc(s: S) -> (res: T, ok: bool)Sourcemin_index
min_index :: proc(s: S) -> (min_index: int, ok: bool)SourceFind the index of the (first) minimum element in a slice.
min_max
min_max :: proc(s: S) -> (min: T, max: T, ok: bool)Sourcenone_of
none_of :: proc(s: S, value: T) -> (bool)Sourcenone_of_proc
none_of_proc :: proc(s: S, f: proc() -> (bool)) -> (bool)Sourcepermute
permute :: proc(iter: ^Permutation_Iterator($T)) -> (ok: bool)SourcePermute a slice in-place.
Note that the first iteration will always be the original, unpermuted slice.
Inputs:
- iter: The iterator created by
make_permutation_iterator.
Returns:
- ok: True if the permutation succeeded, false if the iteration is complete.
prefix_length
prefix_length :: proc(a: T, b: T) -> (n: int)Sourcereturn the prefix length common between slices a and b.
slice.prefix_length([]u8{1, 2, 3, 4}, []u8{1}) -> 1
slice.prefix_length([]u8{1, 2, 3, 4}, []u8{1, 2, 3}) -> 3
slice.prefix_length([]u8{1, 2, 3, 4}, []u8{2, 3, 4}) -> 0ptr_add
ptr_add :: proc(p: P, x: int) -> (^T)Sourceptr_rotate
ptr_rotate :: proc(left: int, mid: ^T, right: int)Sourceptr_sub
ptr_sub :: proc(p: P, x: int) -> (^T)Sourceptr_swap_non_overlapping
ptr_swap_non_overlapping :: proc(x: rawptr, y: rawptr, len: int)Sourceptr_swap_overlapping
ptr_swap_overlapping :: proc(x: rawptr, y: rawptr, len: int)Sourcereduce
reduce :: proc(s: S, initializer: V, f: proc() -> (V)) -> (V)Sourcereduce_reverse
reduce_reverse :: proc(s: S, initializer: V, f: proc() -> (V)) -> (V)Sourcereinterpret
reinterpret :: proc(T: typeid, s: []V) -> ([]U)SourceTurn a slice of one type, into a slice of another type.
Only converts the type and length of the slice itself. The length is rounded down to the nearest whole number of items.
Example:
import "core:fmt"
import "core:slice"
i64s_as_i32s :: proc() {
large_items := []i64{1, 2, 3, 4}
small_items := slice.reinterpret([]i32, large_items)
assert(len(small_items) == 8)
fmt.println(large_items, "->", small_items)
}
bytes_as_i64s :: proc() {
small_items := [12]byte{}
small_items[0] = 1
small_items[8] = 2
large_items := slice.reinterpret([]i64, small_items[:])
assert(len(large_items) == 1) // only enough bytes to make 1 x i64; two would need at least 8 bytes.
fmt.println(small_items, "->", large_items)
}
reinterpret_example :: proc() {
i64s_as_i32s()
bytes_as_i64s()
}Output:
[1, 2, 3, 4] -> [1, 0, 2, 0, 3, 0, 4, 0]
[1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0] -> [1]repeat
repeat :: proc(s: S, count: int, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (b: S, err: runtime.Allocator_Error)Sourcereverse
reverse :: proc(array: T)Sourcereverse_sort
reverse_sort :: proc(data: T)Sourcereverse_sort_by
reverse_sort_by :: proc(data: T, less: proc(i: E, j: E) -> (bool))Sourcereverse_sort_by_cmp
reverse_sort_by_cmp :: proc(data: T, cmp: proc(i: E, j: E) -> (Ordering))Sourcereverse_sort_by_key
reverse_sort_by_key :: proc(data: T, key: proc() -> (K))Sourcerotate_left
rotate_left :: proc(array: T, mid: int)Sourcerotate_right
rotate_right :: proc(array: T, k: int)Sourcescanner
scanner :: proc(s: S, initializer: V, f: proc() -> (V), allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (res: []V, err: runtime.Allocator_Error)Sourcesimple_equal
simple_equal :: proc(a: T, b: T) -> (bool)Sourcesize
size :: proc(a: T) -> (int)SourceGets the byte size of the backing data
sort
sort :: proc(data: T)Sourcesort sorts a slice This sort is not guaranteed to be stable
sort_by
sort_by :: proc(data: T, less: proc(i: E, j: E) -> (bool))Sourcesort_by sorts a slice with a given procedure to test whether two values are ordered "i < j" This sort is not guaranteed to be stable
sort_by_cmp
sort_by_cmp :: proc(data: T, cmp: proc(i: E, j: E) -> (Ordering))Sourcesort_by_cmp_with_data
sort_by_cmp_with_data :: proc(data: T, cmp: proc(i: E, j: E, user_data: rawptr) -> (Ordering), user_data: rawptr)Sourcesort_by_generic_cmp
sort_by_generic_cmp :: proc(data: T, cmp: Generic_Cmp, user_data: rawptr)Sourcesort_by_indices_allocate
sort_by_indices_allocate :: proc(data: T, indices: []int, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (sorted: T)Sourcesort_by_indices_overwrite
sort_by_indices_overwrite :: proc(data: T, indices: []int)Sourcesort_by_key
sort_by_key :: proc(data: T, key: proc() -> (K))SourceTODO(bill): Should sort_by_key exist or is sort_by more than enough?
sort_by_with_data
sort_by_with_data :: proc(data: T, less: proc(i: E, j: E, user_data: rawptr) -> (bool), user_data: rawptr)Sourcesort_by_with_indices
sort_by_with_indices :: proc(data: T, less: proc(i: E, j: E) -> (bool), allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (indices: []int)Sourcesort_by sorts a slice with a given procedure to test whether two values are ordered "i < j" This sort is not guaranteed to be stable
sort_by_with_indices_with_data
sort_by_with_indices_with_data :: proc(data: T, less: proc(i: E, j: E, user_data: rawptr) -> (bool), user_data: rawptr, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (indices: []int)Sourcesort_from_permutation_indices
sort_from_permutation_indices :: proc(data: T, indices: []int)Sourcesort_with_indices
sort_with_indices :: proc(data: T, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> (indices: []int)Sourcesort sorts a slice and returns a slice of the original indices This sort is not guaranteed to be stable
split_at
split_at :: proc(array: T, index: int) -> (a: T, b: T)Sourcesplit_first
split_first :: proc(array: T) -> (first: E, rest: T)Sourcesplit_last
split_last :: proc(array: T) -> (rest: T, last: E)Sourcestable_sort
stable_sort :: proc(data: T)SourceSorts a slice while maintaining the relative order of elements with the same key. For an example see either stable_sort_by or stable_sort_by_cmp.
stable_sort_by
stable_sort_by :: proc(data: T, less: proc(i: E, j: E) -> (bool))SourceSorts a slice while maintaining the relative order of elements with the same key. Two items i and j are ordered if less(i, j) returns true.
Example:
import "core:slice"
import "core:fmt"
stable_sort_by_example :: proc() {
Example :: struct { n: int, s: string }
arr := []Example {
{2, "name"},
{3, "Bill"},
{1, "My"},
{2, "is"}
}
slice.stable_sort_by(arr, proc(i, j: Example) -> bool {
return i.n < j.n
})
for e in arr do fmt.printf("%s ", e.s)
fmt.println()
}Output:
My name is Billstable_sort_by_cmp
stable_sort_by_cmp :: proc(data: T, cmp: proc(i: E, j: E) -> (Ordering))SourceSorts a slice while maintaining the relative order of elements with the same key. The ordering of the any two items is defined by the user-provided cmp.
Example:
import "core:slice"
import "core:fmt"
stable_sort_by_cmp_example :: proc() {
Example :: struct { n: int, s: string }
arr := []Example {
{2, "name"},
{3, "Bill"},
{1, "My"},
{2, "is"}
}
slice.stable_sort_by_cmp(arr, proc(i, j: Example) -> slice.Ordering {
return slice.cmp(i.n, j.n)
})
for e in arr do fmt.printf("%s ", e.s)
fmt.println()
}Output:
My name is Billsuffix_length
suffix_length :: proc(a: T, b: T) -> (n: int)Sourcereturn the suffix length common between slices a and b.
slice.suffix_length([]u8{1, 2, 3, 4}, []u8{1, 2, 3, 4}) -> 4
slice.suffix_length([]u8{1, 2, 3, 4}, []u8{3, 4}) -> 2
slice.suffix_length([]u8{1, 2, 3, 4}, []u8{1}) -> 0
slice.suffix_length([]u8{1, 2, 3, 4}, []u8{1, 3, 5}) -> 0
slice.suffix_length([]u8{3, 4, 5}, []u8{3, 5}) -> 1swap
swap :: proc(array: T, a: int, b: int)Sourceswap_between
swap_between :: proc(a: T, b: T)Sourceswap_with_slice
swap_with_slice :: proc(a: T, b: T, loc = #caller_location)Sourceto_bytes
to_bytes :: proc(s: []T) -> ([]u8)SourceTurn a slice into a byte slice.
See `slice.reinterpret` to go the other way.to_dynamic
to_dynamic :: proc(a: T, allocator: mem.Allocator = context.allocator, loc = #caller_location) -> ([dynamic]E, runtime.Allocator_Error)Sourceto_type
to_type :: proc(buf: []u8, T: typeid) -> (bool, T)SourceTurns a byte slice into a type.
unique
unique :: proc(s: S) -> (S)Source'unique' replaces consecutive runs of equal elements with a single copy. The procedures modifies the slice in-place and returns the modified slice.
unique_proc
unique_proc :: proc(s: S, eq: proc() -> (bool)) -> (S)Source'unique_proc' replaces consecutive runs of equal elements with a single copy using a comparison procedure The procedures modifies the slice in-place and returns the modified slice.
zero
zero :: proc(array: T)Source