Skip to content

Commit

Permalink
feat(stdlib): Add Array.slice function (#727)
Browse files Browse the repository at this point in the history
  • Loading branch information
phated committed Jun 15, 2021
1 parent da71288 commit 66319ca
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
17 changes: 17 additions & 0 deletions compiler/test/stdlib/array.test.gr
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,20 @@ assert Array.unique([>]) == [>]
// Array.join
assert Array.join(", ", [> "a", "b", "c"]) == "a, b, c"
assert Array.join(", ", [>]) == ""

// Array.slice
let testChars = [> 'a', 'b', 'c']

assert Array.slice(0, 1, testChars) == [> 'a']
assert Array.slice(1, Array.length(testChars), testChars) == [> 'b', 'c']
assert Array.slice(0, 0, testChars) == [>]
// Purposefully huge number
assert Array.slice(1, 10000, testChars) == [> 'b', 'c']
// Negative indexing
assert Array.slice(1, -1, testChars) == [> 'b']
assert Array.slice(-2, -1, testChars) == [> 'b']
// Bad order
assert Array.slice(2, 1, testChars) == [>]
assert Array.slice(-1, -2, testChars) == [>]
// Empty
assert Array.slice(1, 4, [>]) == [>]
42 changes: 42 additions & 0 deletions stdlib/array.gr
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,45 @@ export let join = (separator: String, items: Array<String>) => {
Some(s) => s,
}
}

/**
* Slices an array given zero-based start and end indexes. The value
* at the end index will not be included in the result.
*
* If either index is a negative number, it will be treated as a reverse index from
* the end of the array. e.g. slice(1, -1, [> 'a', 'b', 'c']) == [> 'b'].
*
* @param startIndex: Number The index of the array where the slice will begin (inclusive)
* @param endIndex: Number The index of the array where the slice will end (exclusive)
* @param array: Array<a> The array to be sliced
* @returns Array<a> The subset of the array that was sliced
*/
export let slice = (startIndex, endIndex, array) => {
let arrayLength = length(array)

let wrapNegativeIndex = idx => {
if (idx >= 0) {
idx
} else {
arrayLength + idx
}
}

let startIndex = wrapNegativeIndex(startIndex)
let endIndex = wrapNegativeIndex(endIndex)
// Ensure we aren't working with an `end` value that is too big
let endIndex = if (endIndex > arrayLength) {
arrayLength
} else {
endIndex
}

let newLength = endIndex - startIndex;
if (newLength < 0) {
[>]
} else if (newLength > arrayLength) {
array
} else {
init(newLength, n => array[startIndex + n])
}
}

0 comments on commit 66319ca

Please sign in to comment.