push/pop/shift/unshift (and fix sort()
This commit is contained in:
parent
2abf3558d5
commit
a8fd79a990
|
|
@ -1,3 +1,5 @@
|
|||
import { type Value, toValue, toNull } from 'reefvm'
|
||||
|
||||
export const list = {
|
||||
slice: (list: any[], start: number, end?: number) => list.slice(start, end),
|
||||
map: async (list: any[], cb: Function) => {
|
||||
|
|
@ -40,9 +42,41 @@ export const list = {
|
|||
return true
|
||||
},
|
||||
|
||||
// mutating
|
||||
push: (list: Value, item: Value) => {
|
||||
if (list.type !== 'array') return toNull()
|
||||
return toValue(list.value.push(item))
|
||||
},
|
||||
pop: (list: Value) => {
|
||||
if (list.type !== 'array') return toNull()
|
||||
return toValue(list.value.pop())
|
||||
},
|
||||
shift: (list: Value) => {
|
||||
if (list.type !== 'array') return toNull()
|
||||
return toValue(list.value.shift())
|
||||
},
|
||||
unshift: (list: Value, item: Value) => {
|
||||
if (list.type !== 'array') return toNull()
|
||||
return toValue(list.value.unshift(item))
|
||||
},
|
||||
splice: (list: Value, start: Value, deleteCount: Value, ...items: Value[]) => {
|
||||
const realList = list.value as any[]
|
||||
const realStart = start.value as number
|
||||
const realDeleteCount = deleteCount.value as number
|
||||
const realItems = items.map(item => item.value)
|
||||
return toValue(realList.splice(realStart, realDeleteCount, ...realItems))
|
||||
},
|
||||
|
||||
// sequence operations
|
||||
reverse: (list: any[]) => list.slice().reverse(),
|
||||
sort: (list: any[], cb?: (a: any, b: any) => number) => list.slice().sort(cb),
|
||||
sort: async (list: any[], cb?: (a: any, b: any) => number) => {
|
||||
const arr = [...list]
|
||||
if (!cb) return arr.sort()
|
||||
for (let i = 0; i < arr.length; i++)
|
||||
for (let j = i + 1; j < arr.length; j++)
|
||||
if ((await cb(arr[i], arr[j])) > 0) [arr[i], arr[j]] = [arr[j], arr[i]]
|
||||
return arr
|
||||
},
|
||||
concat: (...lists: any[][]) => lists.flat(1),
|
||||
flatten: (list: any[], depth: number = 1) => list.flat(depth),
|
||||
unique: (list: any[]) => Array.from(new Set(list)),
|
||||
|
|
@ -86,4 +120,13 @@ export const list = {
|
|||
}
|
||||
return groups
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// raw functions deal directly in Value types, meaning we can modify collection
|
||||
// careful - they MUST return a Value!
|
||||
; (list.splice as any).raw = true
|
||||
; (list.push as any).raw = true
|
||||
; (list.pop as any).raw = true
|
||||
; (list.shift as any).raw = true
|
||||
; (list.unshift as any).raw = true
|
||||
|
|
@ -341,6 +341,84 @@ describe('collections', () => {
|
|||
await expect(`list.index-of [1 2 3] 5`).toEvaluateTo(-1, globals)
|
||||
})
|
||||
|
||||
test('list.push adds to end and mutates array', async () => {
|
||||
await expect(`arr = [1 2]; list.push arr 3; arr`).toEvaluateTo([1, 2, 3], globals)
|
||||
})
|
||||
|
||||
test('list.push returns the size of the array', async () => {
|
||||
await expect(`arr = [1 2]; arr | list.push 3`).toEvaluateTo(3, globals)
|
||||
})
|
||||
|
||||
test('list.pop removes from end and mutates array', async () => {
|
||||
await expect(`arr = [1 2 3]; list.pop arr; arr`).toEvaluateTo([1, 2], globals)
|
||||
})
|
||||
|
||||
test('list.pop returns removed element', async () => {
|
||||
await expect(`list.pop [1 2 3]`).toEvaluateTo(3, globals)
|
||||
})
|
||||
|
||||
test('list.pop returns null for empty array', async () => {
|
||||
await expect(`list.pop []`).toEvaluateTo(null, globals)
|
||||
})
|
||||
|
||||
test('list.shift removes from start and mutates array', async () => {
|
||||
await expect(`arr = [1 2 3]; list.shift arr; arr`).toEvaluateTo([2, 3], globals)
|
||||
})
|
||||
|
||||
test('list.shift returns removed element', async () => {
|
||||
await expect(`list.shift [1 2 3]`).toEvaluateTo(1, globals)
|
||||
})
|
||||
|
||||
test('list.shift returns null for empty array', async () => {
|
||||
await expect(`list.shift []`).toEvaluateTo(null, globals)
|
||||
})
|
||||
|
||||
test('list.unshift adds to start and mutates array', async () => {
|
||||
await expect(`arr = [2 3]; list.unshift arr 1; arr`).toEvaluateTo([1, 2, 3], globals)
|
||||
})
|
||||
|
||||
test('list.unshift returns the length of the array', async () => {
|
||||
await expect(`arr = [2 3]; arr | list.unshift 1`).toEvaluateTo(3, globals)
|
||||
})
|
||||
|
||||
test('list.splice removes elements and mutates array', async () => {
|
||||
await expect(`arr = [1 2 3 4 5]; list.splice arr 1 2; arr`).toEvaluateTo([1, 4, 5], globals)
|
||||
})
|
||||
|
||||
test('list.splice returns removed elements', async () => {
|
||||
await expect(`list.splice [1 2 3 4 5] 1 2`).toEvaluateTo([2, 3], globals)
|
||||
})
|
||||
|
||||
test('list.splice from start', async () => {
|
||||
await expect(`list.splice [1 2 3 4 5] 0 2`).toEvaluateTo([1, 2], globals)
|
||||
})
|
||||
|
||||
test('list.splice to end', async () => {
|
||||
await expect(`arr = [1 2 3 4 5]; list.splice arr 3 2; arr`).toEvaluateTo([1, 2, 3], globals)
|
||||
})
|
||||
|
||||
test('list.sort with no callback sorts ascending', async () => {
|
||||
await expect(`list.sort [3 1 4 1 5] null`).toEvaluateTo([1, 1, 3, 4, 5], globals)
|
||||
})
|
||||
|
||||
test('list.sort with callback sorts using comparator', async () => {
|
||||
await expect(`
|
||||
desc = do a b:
|
||||
b - a
|
||||
end
|
||||
list.sort [3 1 4 1 5] desc
|
||||
`).toEvaluateTo([5, 4, 3, 1, 1], globals)
|
||||
})
|
||||
|
||||
test('list.sort with callback for strings by length', async () => {
|
||||
await expect(`
|
||||
by-length = do a b:
|
||||
(length a) - (length b)
|
||||
end
|
||||
list.sort ['cat' 'a' 'dog' 'elephant'] by-length
|
||||
`).toEvaluateTo(['a', 'cat', 'dog', 'elephant'], globals)
|
||||
})
|
||||
|
||||
test('list.any? checks if any element matches', async () => {
|
||||
await expect(`
|
||||
gt-three = do x: x > 3 end
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user