Skip to content

Commit eb24e38

Browse files
committed
feat(list): adding list:window
1 parent aa47d4e commit eb24e38

File tree

2 files changed

+182
-115
lines changed

2 files changed

+182
-115
lines changed

List.ark

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,3 +584,33 @@
584584
# insert anywhere
585585
(let _parts (partition _L (fun (elem i &_index) (< i _index))))
586586
(concat (head _parts) _value (@ _parts 1)) })) }))
587+
588+
# @brief Create a sliding window of a given size on a list
589+
# @details The original list is not modified
590+
# @param _L list to iterate over
591+
# @param _size window size, must be at least 1
592+
# @param _f function to call with the window
593+
# =begin
594+
# (let f (fun (lst) (print lst))
595+
# (list:window [1 2 3 4 5] 3 f)
596+
# # [1 2 3]
597+
# # [2 3 4]
598+
# # [3 4 5]
599+
# =end
600+
# @author https://github.com/SuperFola
601+
(let window (fun (_L _size _f) {
602+
(assert (> _size 0) "window size must be at least 1")
603+
604+
(mut _i 0)
605+
(while (< _i (len _L)) {
606+
(mut _win [])
607+
(mut _j 0)
608+
(while (< _j _size) {
609+
(append! _win (@ _L (+ _i _j)))
610+
(set _j (+ 1 _j)) })
611+
612+
(_f _win)
613+
614+
(if (>= (+ _i _size) (len _L))
615+
(set _i (len _L)))
616+
(set _i (+ 1 _i)) })}))

tests/list-tests.ark

Lines changed: 152 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -7,123 +7,160 @@
77
(let zipped [[1 5] [2 6] [3 7] [4 8]])
88

99
(test:suite list {
10-
(test:eq (builtin__list:reverse a) (list:reverse a))
11-
(test:eq (builtin__list:reverse []) (list:reverse []))
10+
(test:case "builtins" {
11+
(test:eq (builtin__list:reverse a) (list:reverse a))
12+
(test:eq (builtin__list:reverse []) (list:reverse []))
13+
14+
(test:eq (builtin__list:find a 0) (list:find a 0))
15+
(test:eq (builtin__list:find a 1) (list:find a 1))
16+
17+
(test:eq (builtin__list:slice a 1 2 1) (list:slice a 1 2 1))
18+
19+
(test:eq (builtin__list:sort [9 8 1]) (list:sort [9 8 1]))
20+
(test:eq (builtin__list:sort []) (list:sort []))
21+
22+
(test:eq (builtin__list:fill 5 nil) (list:fill 5 nil))
23+
24+
(test:eq (builtin__list:setAt a 0 5) (list:setAt a 0 5)) })
25+
26+
(test:case "size" {
27+
(test:eq (list:size []) 0)
28+
(test:eq (list:size [1 2 3]) 3) })
29+
30+
(test:case "forEach" {
31+
(list:forEach a (fun (e) {
32+
# just assert we have something, basically it's just a while + @
33+
(test:neq e nil)})) })
34+
35+
(test:case "product" {
36+
(test:eq (list:product b) (* 4 5 6))
37+
(test:eq (list:product []) 1) })
38+
39+
(test:case "sum" {
40+
(test:eq (list:sum b) (+ 4 5 6))
41+
(test:eq (list:sum []) 0) })
42+
43+
(test:case "min" {
44+
(test:eq (list:min []) nil)
45+
(test:eq (list:min b) 4)
46+
(test:eq (list:min [-1]) -1) })
47+
48+
(test:case "max" {
49+
(test:eq (list:max []) nil)
50+
(test:eq (list:max b) 6)
51+
(test:eq (list:max [-1]) -1) })
52+
53+
(test:case "drop" {
54+
(test:eq (list:drop a 0) [1 2 3])
55+
(test:eq (list:drop a 1) [2 3])
56+
(test:eq (list:drop a 2) [3]) })
57+
58+
(test:case "dropWhile" {
59+
(test:eq (list:dropWhile a (fun (c) (< c 0))) [1 2 3])
60+
(test:eq (list:dropWhile a (fun (c) (< c 2))) [2 3])
61+
(test:eq (list:dropWhile a (fun (c) (< c 5))) []) })
62+
63+
(test:case "filter" {
64+
(test:eq (list:filter a math:even) [2])
65+
(test:eq (list:filter a (fun (e) (> e 100))) [])
66+
(test:eq (list:filter [] (fun (e) (> e 100))) []) })
67+
68+
(test:case "map" {
69+
(test:eq (list:map b (fun (e) (* e e))) [16 25 36])
70+
(test:eq (list:map [] (fun (e) (* e e))) []) })
71+
72+
(test:case "reduce" {
73+
(test:eq (list:reduce a (fun (x y) (- x y))) -4) })
74+
75+
(test:case "flatten" {
76+
(test:eq (list:flatten []) [])
77+
(test:eq (list:flatten [[]]) [])
78+
(test:eq (list:flatten [[1]]) [1])
79+
(test:eq (list:flatten zipped) [1 5 2 6 3 7 4 8]) })
80+
81+
(test:case "flatMap" {
82+
(test:eq (list:flatMap [] (fun (a) [a a])) [])
83+
(test:eq (list:flatMap a (fun (a) (* 2 a))) [2 4 6])
84+
(test:eq (list:flatMap a (fun (a) [a a])) [1 1 2 2 3 3]) })
85+
86+
(test:case "take" {
87+
(test:eq (list:take a 1) [1])
88+
(test:eq (list:take a 100) a) })
89+
90+
(test:case "takeWhile" {
91+
(test:eq (list:takeWhile a (fun (c) (< c 0))) [])
92+
(test:eq (list:takeWhile a (fun (c) (< c 2))) [1])
93+
(test:eq (list:takeWhile a (fun (c) (< c 3))) [1 2])
94+
(test:eq (list:takeWhile a (fun (c) (< c 5))) [1 2 3]) })
95+
96+
(test:case "partition" {
97+
(test:eq (list:partition a (fun (c i) (= 0 (mod c 2)))) [[2] [1 3]])
98+
(test:eq (list:partition a (fun (c i) (= 0 c))) [[] [1 2 3]])
99+
(test:eq (list:partition [] (fun (c i) (= 0 c))) [[] []]) })
100+
101+
(test:case "unzip" {
102+
(test:eq (list:unzip zipped) [[1 2 3 4] [5 6 7 8]])
103+
(test:eq (list:unzip []) [[] []]) })
104+
105+
(test:case "zip" {
106+
(test:eq (list:zip a b) [[1 4] [2 5] [3 6]])
107+
(test:eq (list:zip [] []) []) })
108+
109+
(test:case "foldLeft" {
110+
(test:eq (list:foldLeft [] 0 (fun (x y) (+ x y))) 0)
111+
(test:eq (list:foldLeft ["1" "2" "3"] "" (fun (x y) (+ x y))) "123")
112+
(test:eq (list:foldLeft a 0 (fun (x y) (+ x y))) 6) })
12113

13-
(test:eq (builtin__list:find a 0) (list:find a 0))
14-
(test:eq (builtin__list:find a 1) (list:find a 1))
15-
16-
(test:eq (builtin__list:slice a 1 2 1) (list:slice a 1 2 1))
17-
18-
(test:eq (builtin__list:sort [9 8 1]) (list:sort [9 8 1]))
19-
(test:eq (builtin__list:sort []) (list:sort []))
20-
21-
(test:eq (builtin__list:fill 5 nil) (list:fill 5 nil))
22-
23-
(test:eq (builtin__list:setAt a 0 5) (list:setAt a 0 5))
24-
25-
(test:eq (list:size []) 0)
26-
(test:eq (list:size [1 2 3]) 3)
27-
28-
(list:forEach a (fun (e) {
29-
# just assert we have something, basically it's just a while + @
30-
(test:neq e nil)}))
31-
32-
(test:eq (list:product b) (* 4 5 6))
33-
(test:eq (list:product []) 1)
34-
35-
(test:eq (list:sum b) (+ 4 5 6))
36-
(test:eq (list:sum []) 0)
37-
38-
(test:eq (list:min []) nil)
39-
(test:eq (list:min b) 4)
40-
(test:eq (list:min [-1]) -1)
41-
42-
(test:eq (list:max []) nil)
43-
(test:eq (list:max b) 6)
44-
(test:eq (list:max [-1]) -1)
45-
46-
(test:eq (list:drop a 0) [1 2 3])
47-
(test:eq (list:drop a 1) [2 3])
48-
(test:eq (list:drop a 2) [3])
49-
50-
(test:eq (list:dropWhile a (fun (c) (< c 0))) [1 2 3])
51-
(test:eq (list:dropWhile a (fun (c) (< c 2))) [2 3])
52-
(test:eq (list:dropWhile a (fun (c) (< c 5))) [])
53-
54-
(test:eq (list:filter a math:even) [2])
55-
(test:eq (list:filter a (fun (e) (> e 100))) [])
56-
(test:eq (list:filter [] (fun (e) (> e 100))) [])
57-
58-
(test:eq (list:map b (fun (e) (* e e))) [16 25 36])
59-
(test:eq (list:map [] (fun (e) (* e e))) [])
60-
61-
(test:eq (list:reduce a (fun (x y) (- x y))) -4)
62-
63-
(test:eq (list:flatten []) [])
64-
(test:eq (list:flatten [[]]) [])
65-
(test:eq (list:flatten [[1]]) [1])
66-
(test:eq (list:flatten zipped) [1 5 2 6 3 7 4 8])
67-
68-
(test:eq (list:flatMap [] (fun (a) [a a])) [])
69-
(test:eq (list:flatMap a (fun (a) (* 2 a))) [2 4 6])
70-
(test:eq (list:flatMap a (fun (a) [a a])) [1 1 2 2 3 3])
71-
72-
(test:eq (list:take a 1) [1])
73-
(test:eq (list:take a 100) a)
74-
75-
(test:eq (list:takeWhile a (fun (c) (< c 0))) [])
76-
(test:eq (list:takeWhile a (fun (c) (< c 2))) [1])
77-
(test:eq (list:takeWhile a (fun (c) (< c 3))) [1 2])
78-
(test:eq (list:takeWhile a (fun (c) (< c 5))) [1 2 3])
79-
80-
(test:eq (list:partition a (fun (c i) (= 0 (mod c 2)))) [[2] [1 3]])
81-
(test:eq (list:partition a (fun (c i) (= 0 c))) [[] [1 2 3]])
82-
(test:eq (list:partition [] (fun (c i) (= 0 c))) [[] []])
83-
84-
(test:eq (list:unzip zipped) [[1 2 3 4] [5 6 7 8]])
85-
(test:eq (list:unzip []) [[] []])
86-
87-
(test:eq (list:zip a b) [[1 4] [2 5] [3 6]])
88-
(test:eq (list:zip [] []) [])
89-
90-
(test:eq (list:foldLeft [] 0 (fun (x y) (+ x y))) 0)
91-
(test:eq (list:foldLeft ["1" "2" "3"] "" (fun (x y) (+ x y))) "123")
92-
(test:eq (list:foldLeft a 0 (fun (x y) (+ x y))) 6)
93-
94-
(test:eq (list:zipWithIndex a) [[0 1] [1 2] [2 3]])
95-
(test:eq (list:zipWithIndex []) [])
114+
(test:case "zipWithIndex" {
115+
(test:eq (list:zipWithIndex a) [[0 1] [1 2] [2 3]])
116+
(test:eq (list:zipWithIndex []) []) })
96117

97118
(test:eq a [1 2 3])
98119
(test:eq b [4 5 6])
99120

100-
(test:expect (list:forAll a (fun (e) (< e 4))))
101-
(test:expect (not (list:forAll a (fun (e) (< e 2)))))
102-
(test:expect (list:forAll [] (fun (e) (= e 2))))
103-
(test:expect (list:any a (fun (e) (< e 2))))
104-
(test:expect (not (list:any a (fun (e) (> e 8)))))
105-
(test:expect (not (list:any [] (fun (e) (= e 8)))))
106-
107-
(test:eq (list:countIf a (fun (e) (= 0 (mod e 2)))) 1)
108-
(test:eq (list:countIf a (fun (e) (= 1 (mod e 2)))) 2)
109-
(test:eq (list:countIf [] (fun (e) (= 1 (mod e 2)))) 0)
110-
111-
(test:eq (list:iterate 0 (fun (x) (+ 1 x)) 5) [0 1 2 3 4])
112-
(test:eq (list:iterate 0 (fun (x) (+ 1 x)) 5) (list:iota 0 5))
113-
(test:eq (list:iterate "" (fun (x) (+ x "a")) 5) ["" "a" "aa" "aaa" "aaaa"])
114-
(test:eq (list:iterate 0 (fun (x) (+ 1 x)) 1) [0])
115-
116-
(test:eq (list:chunkBy [1 2] 1) [[1] [2]])
117-
(test:eq (list:chunkBy [1 2 3] 3) [[1 2 3]])
118-
(test:eq (list:chunkBy [1 2 3 4] 3) [[1 2 3] [4]])
119-
(test:eq (list:chunkBy [1 2 3 4 5] 3) [[1 2 3] [4 5]])
120-
(test:eq (list:chunkBy [1 2 3 4 5 6] 3) [[1 2 3] [4 5 6]])
121-
122-
(test:eq (list:insert [0] 1 4) [0 4])
123-
(test:eq (list:insert [0] 0 4) [4 0])
124-
(test:eq (list:insert [0 9] 0 4) [4 0 9])
125-
(test:eq (list:insert [0 9] 1 4) [0 4 9])
126-
(test:eq (list:insert [0] 1 [1 2]) [0 1 2])
127-
(test:eq (list:insert [0] 0 [1 2]) [1 2 0])
128-
(test:eq (list:insert [0 9] 0 [1 2]) [1 2 0 9])
129-
(test:eq (list:insert [0 9] 1 [1 2]) [0 1 2 9]) })
121+
(test:case "forAll, any" {
122+
(test:expect (list:forAll a (fun (e) (< e 4))))
123+
(test:expect (not (list:forAll a (fun (e) (< e 2)))))
124+
(test:expect (list:forAll [] (fun (e) (= e 2))))
125+
(test:expect (list:any a (fun (e) (< e 2))))
126+
(test:expect (not (list:any a (fun (e) (> e 8)))))
127+
(test:expect (not (list:any [] (fun (e) (= e 8))))) })
128+
129+
(test:case "countIf" {
130+
(test:eq (list:countIf a (fun (e) (= 0 (mod e 2)))) 1)
131+
(test:eq (list:countIf a (fun (e) (= 1 (mod e 2)))) 2)
132+
(test:eq (list:countIf [] (fun (e) (= 1 (mod e 2)))) 0) })
133+
134+
(test:case "iterate" {
135+
(test:eq (list:iterate 0 (fun (x) (+ 1 x)) 5) [0 1 2 3 4])
136+
(test:eq (list:iterate 0 (fun (x) (+ 1 x)) 5) (list:iota 0 5))
137+
(test:eq (list:iterate "" (fun (x) (+ x "a")) 5) ["" "a" "aa" "aaa" "aaaa"])
138+
(test:eq (list:iterate 0 (fun (x) (+ 1 x)) 1) [0]) })
139+
140+
(test:case "chunkBy" {
141+
(test:eq (list:chunkBy [1 2] 1) [[1] [2]])
142+
(test:eq (list:chunkBy [1 2 3] 3) [[1 2 3]])
143+
(test:eq (list:chunkBy [1 2 3 4] 3) [[1 2 3] [4]])
144+
(test:eq (list:chunkBy [1 2 3 4 5] 3) [[1 2 3] [4 5]])
145+
(test:eq (list:chunkBy [1 2 3 4 5 6] 3) [[1 2 3] [4 5 6]]) })
146+
147+
(test:case "insert" {
148+
(test:eq (list:insert [0] 1 4) [0 4])
149+
(test:eq (list:insert [0] 0 4) [4 0])
150+
(test:eq (list:insert [0 9] 0 4) [4 0 9])
151+
(test:eq (list:insert [0 9] 1 4) [0 4 9])
152+
(test:eq (list:insert [0] 1 [1 2]) [0 1 2])
153+
(test:eq (list:insert [0] 0 [1 2]) [1 2 0])
154+
(test:eq (list:insert [0 9] 0 [1 2]) [1 2 0 9])
155+
(test:eq (list:insert [0 9] 1 [1 2]) [0 1 2 9]) })
156+
157+
(test:case "window" {
158+
(list:window [] 1 (fun (l) (test:expect false)))
159+
(mut i 1)
160+
(list:window [1 2 3 4] 2
161+
(fun (l) {
162+
(test:eq (@ l 0) i)
163+
(test:eq (@ l 1) (+ 1 i))
164+
(set i (+ 1 i))
165+
(test:eq 2 (len l)) }))
166+
(test:eq i 4) }) })

0 commit comments

Comments
 (0)