diff options
| author | frozolotl <44589151+frozolotl@users.noreply.github.com> | 2024-03-04 10:03:35 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-04 09:03:35 +0000 |
| commit | 879bd1a1cef506514123703f8031a8c203a2c0eb (patch) | |
| tree | d03cb31e446db4f57fdeffaca85585f9752d06fe | |
| parent | 086bca9576d4faa05f48283462a883cbd585a69f (diff) | |
Add `chunks` method to array (#3539)
Co-authored-by: Laurenz <laurmaedje@gmail.com>
| -rw-r--r-- | crates/typst/src/foundations/array.rs | 32 | ||||
| -rw-r--r-- | tests/typ/compiler/array.typ | 20 |
2 files changed, 51 insertions, 1 deletions
diff --git a/crates/typst/src/foundations/array.rs b/crates/typst/src/foundations/array.rs index 1df24bd8..a1e93d7b 100644 --- a/crates/typst/src/foundations/array.rs +++ b/crates/typst/src/foundations/array.rs @@ -1,6 +1,6 @@ use std::cmp::Ordering; use std::fmt::{Debug, Formatter}; -use std::num::NonZeroI64; +use std::num::{NonZeroI64, NonZeroUsize}; use std::ops::{Add, AddAssign}; use ecow::{eco_format, EcoString, EcoVec}; @@ -724,6 +724,36 @@ impl Array { Array(vec) } + /// Splits an array into non-overlapping chunks, starting at the beginning, + /// ending with a single remainder chunk. + /// + /// All chunks but the last have `chunk-size` elements. + /// If `exact` is set to `{true}`, the remainder is dropped if it + /// contains less than `chunk-size` elements. + /// + /// ```example + /// #let array = (1, 2, 3, 4, 5, 6, 7, 8) + /// #array.chunks(3) + /// #array.chunks(3, exact: true) + /// ``` + #[func] + pub fn chunks( + self, + /// How many elements each chunk may at most contain. + chunk_size: NonZeroUsize, + /// Whether to keep the remainder if its size is less than `chunk-size`. + #[named] + #[default(false)] + exact: bool, + ) -> Array { + let to_array = |chunk| Array::from(chunk).into_value(); + if exact { + self.0.chunks_exact(chunk_size.get()).map(to_array).collect() + } else { + self.0.chunks(chunk_size.get()).map(to_array).collect() + } + } + /// Return a sorted version of this array, optionally by a given key /// function. The sorting algorithm used is stable. /// diff --git a/tests/typ/compiler/array.typ b/tests/typ/compiler/array.typ index 9ff29480..4a1948ff 100644 --- a/tests/typ/compiler/array.typ +++ b/tests/typ/compiler/array.typ @@ -237,6 +237,26 @@ #test((1, 2, "b").intersperse("a"), (1, "a", 2, "a", "b")) --- +// Test the `chunks` method. +#test(().chunks(10), ()) +#test((1, 2, 3).chunks(10), ((1, 2, 3),)) +#test((1, 2, 3, 4, 5, 6).chunks(3), ((1, 2, 3), (4, 5, 6))) +#test((1, 2, 3, 4, 5, 6, 7, 8).chunks(3), ((1, 2, 3), (4, 5, 6), (7, 8))) + +#test(().chunks(10, exact: true), ()) +#test((1, 2, 3).chunks(10, exact: true), ()) +#test((1, 2, 3, 4, 5, 6).chunks(3, exact: true), ((1, 2, 3), (4, 5, 6))) +#test((1, 2, 3, 4, 5, 6, 7, 8).chunks(3, exact: true), ((1, 2, 3), (4, 5, 6))) + +--- +// Error: 19-20 number must be positive +#(1, 2, 3).chunks(0) + +--- +// Error: 19-21 number must be positive +#(1, 2, 3).chunks(-5) + +--- // Test the `sorted` method. #test(().sorted(), ()) #test(().sorted(key: x => x), ()) |
