Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add array manipulation functions #629

Merged
merged 7 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/std/array.ab
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,52 @@ pub fun includes(array, value) {
let result = array_first_index(array, value)
return result >= 0
}

/// Returns the first element in the array.
pub fun first(array) {
return array[0]
}

/// Returns the last element in the array.
pub fun last(array) {
let index = len(array) - 1
return array[index]
}

/// Removes an element at the index from the array; this will have no effect
/// if the index is before the start or beyond the end of the array.
pub fun remove_at(ref array: [], index: Num): Null {
let offset = index + 1
let length = len(array)
array = array[0..index] + array[offset..length]
}
hdwalters marked this conversation as resolved.
Show resolved Hide resolved

/// Removes an element at the index from the array, and returns it; this will
/// have no effect if the index is before the start or beyond the end of the
/// array.
pub fun extract_at(ref array, index) {
let element = array[index]
let offset = index + 1
let length = len(array)
array = array[0..index] + array[offset..length]
return element
}

/// Removes the last element from the array, and returns it; this will have
/// no effect if the array is empty.
pub fun pop(ref array) {
let length = len(array)
let index = length - 1
let element = array[index]
array = array[0..index]
return element
}

/// Removes the first element from the array, and returns it; this will have
/// no effect if the array is empty.
pub fun shift(ref array) {
let length = len(array)
let element = array[0]
array = array[1..length]
return element
}
25 changes: 25 additions & 0 deletions src/tests/stdlib/array_extract_at.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { extract_at } from "std/array"

// Output
// Value at -5: "" (4) [zero one two three]
// Value at -4: "zero" (4) [zero one two three]
// Value at -3: "one" (4) [zero one two three]
// Value at -2: "two" (4) [zero one two three]
// Value at -1: "three" (4) [zero one two three]
// Value at 0: "zero" (3) [one two three]
// Value at 1: "one" (3) [zero two three]
// Value at 2: "two" (3) [zero one three]
// Value at 3: "three" (3) [zero one two]
// Value at 4: "" (4) [zero one two three]

fun test_extract(data: [Text], index: Num): Null {
let value = extract_at(data, index)
echo "Value at {index}: \"{value}\" ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
for index in -5..=4 {
test_extract(numbers, index)
}
}
17 changes: 17 additions & 0 deletions src/tests/stdlib/array_first.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { first } from "std/array"

// Output
// First of numbers: "zero" (4) [zero one two three]
// First of empty: "" (0) []

fun test_first(label: Text, data: [Text]): Null {
let value = first(data)
echo "First of {label}: \"{value}\" ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
let empty = [Text]
test_first("numbers", numbers)
test_first("empty", empty)
}
22 changes: 18 additions & 4 deletions src/tests/stdlib/array_first_index.ab
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
import * from "std/array"
import { array_first_index } from "std/array"

// Output
// 2
// Index of "zero": 0
// Index of "one": 1
// Index of "two": 2
// Index of "three": 3
// Index of "four": -1

fun test_index(data: [Text], value: Text): Null {
let index = array_first_index(data, value)
echo "Index of \"{value}\": {index}"
}

main {
echo array_first_index([1, 2, 3, 4], 3)
}
let numbers = ["zero", "one", "two", "three", "two", "one", "zero"]
test_index(numbers, "zero")
test_index(numbers, "one")
test_index(numbers, "two")
test_index(numbers, "three")
test_index(numbers, "four")
}
17 changes: 17 additions & 0 deletions src/tests/stdlib/array_last.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { last } from "std/array"

// Output
// Last of numbers: "three" (4) [zero one two three]
// Last of empty: "" (0) []

fun test_last(label: Text, data: [Text]): Null {
let value = last(data)
echo "Last of {label}: \"{value}\" ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
let empty = [Text]
test_last("numbers", numbers)
test_last("empty", empty)
}
17 changes: 17 additions & 0 deletions src/tests/stdlib/array_pop.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { pop } from "std/array"

// Output
// Popped from numbers: "three" (3) [zero one two]
// Popped from empty: "" (0) []

fun test_pop(label: Text, data: [Text]): Null {
let value = pop(data)
echo "Popped from {label}: \"{value}\" ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
let empty = [Text]
test_pop("numbers", numbers)
test_pop("empty", empty)
}
25 changes: 25 additions & 0 deletions src/tests/stdlib/array_remove_at.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { remove_at } from "std/array"

// Output
// Array after -5: (4) [zero one two three]
// Array after -4: (4) [zero one two three]
// Array after -3: (4) [zero one two three]
// Array after -2: (4) [zero one two three]
// Array after -1: (4) [zero one two three]
// Array after 0: (3) [one two three]
// Array after 1: (3) [zero two three]
// Array after 2: (3) [zero one three]
// Array after 3: (3) [zero one two]
// Array after 4: (4) [zero one two three]

fun test_remove(data: [Text], index: Num): Null {
remove_at(data, index)
echo "Array after {index}: ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
for index in -5..=4 {
test_remove(numbers, index)
}
}
21 changes: 21 additions & 0 deletions src/tests/stdlib/array_remove_each.ab
hdwalters marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { remove_at } from "std/array"

// Output
// Array before 1: (4) [zero one two three]
// Array after 1: (3) [zero two three]
// Array after 2: (2) [zero three]
// Array after 3: (1) [zero]
// Array after 4: (1) [zero]

main {
let numbers = ["zero", "one", "two", "three"]
echo "Array before 1: ({len(numbers)}) [{numbers}]"
remove_at(numbers, 1)
echo "Array after 1: ({len(numbers)}) [{numbers}]"
remove_at(numbers, 1)
echo "Array after 2: ({len(numbers)}) [{numbers}]"
remove_at(numbers, 1)
echo "Array after 3: ({len(numbers)}) [{numbers}]"
remove_at(numbers, 1)
echo "Array after 4: ({len(numbers)}) [{numbers}]"
}
23 changes: 18 additions & 5 deletions src/tests/stdlib/array_search.ab
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import * from "std/array"
import { array_search } from "std/array"

// Output
// 6
// Indices of "zero": [0 6]
// Indices of "one": [1 5]
// Indices of "two": [2 4]
// Indices of "three": [3]
// Indices of "four": []

fun test_search(data: [Text], value: Text): Null {
let indices = array_search(data, value)
echo "Indices of \"{value}\": [{indices}]"
}

main {
let result = array_search([1, 2, 3, 4, 3], 3)
echo result[0]+result[1]
}
let numbers = ["zero", "one", "two", "three", "two", "one", "zero"]
test_search(numbers, "zero")
test_search(numbers, "one")
test_search(numbers, "two")
test_search(numbers, "three")
test_search(numbers, "four")
}
17 changes: 17 additions & 0 deletions src/tests/stdlib/array_shift.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { shift } from "std/array"

// Output
// Shifted from numbers: "zero" (3) [one two three]
// Shifted from empty: "" (0) []

fun test_shift(label: Text, data: [Text]): Null {
let value = shift(data)
echo "Shifted from {label}: \"{value}\" ({len(data)}) [{data}]"
}

main {
let numbers = ["zero", "one", "two", "three"]
let empty = [Text]
test_shift("numbers", numbers)
test_shift("empty", empty)
}
Loading