From 5c6434d4cef8bd1bf3ad2c77f379a8b174939ab9 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Mon, 21 Aug 2023 19:31:27 +0530 Subject: [PATCH] Add intersperse() method for arrays (#1897) --- crates/typst/src/eval/array.rs | 24 ++++++++++++++++++++++++ crates/typst/src/eval/methods.rs | 1 + docs/reference/types.md | 6 ++++++ tests/typ/compiler/array.typ | 7 +++++++ 4 files changed, 38 insertions(+) diff --git a/crates/typst/src/eval/array.rs b/crates/typst/src/eval/array.rs index b98c92968..9afae865e 100644 --- a/crates/typst/src/eval/array.rs +++ b/crates/typst/src/eval/array.rs @@ -287,6 +287,30 @@ impl Array { Ok(result) } + /// Returns an array with a copy of the separator value placed between + /// adjacent elements. + pub fn intersperse(&self, sep: Value) -> Array { + // TODO: Use https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.intersperse + // once it is stabilized. + let size = match self.len() { + 0 => return Array::new(), + n => (2 * n) - 1, + }; + let mut vec = EcoVec::with_capacity(size); + let mut iter = self.iter().cloned(); + + if let Some(first) = iter.next() { + vec.push(first); + } + + for value in iter { + vec.push(sep.clone()); + vec.push(value); + } + + Array(vec) + } + /// Zips the array with another array. If the two arrays are of unequal length, it will only /// zip up until the last element of the smaller array and the remaining elements will be /// ignored. The return value is an array where each element is yet another array of size 2. diff --git a/crates/typst/src/eval/methods.rs b/crates/typst/src/eval/methods.rs index a47d945b1..6df504b5e 100644 --- a/crates/typst/src/eval/methods.rs +++ b/crates/typst/src/eval/methods.rs @@ -154,6 +154,7 @@ pub fn call( let last = args.named("last")?; array.join(sep, last).at(span)? } + "intersperse" => array.intersperse(args.expect("separator")?).into_value(), "sorted" => array.sorted(vm, span, args.named("key")?)?.into_value(), "zip" => array.zip(args.expect("other")?).into_value(), "enumerate" => array diff --git a/docs/reference/types.md b/docs/reference/types.md index 3979a4546..b0ee1bd11 100644 --- a/docs/reference/types.md +++ b/docs/reference/types.md @@ -1029,6 +1029,12 @@ Combine all items in the array into one. An alternative separator between the last two items - returns: any +### intersperse() +Returns a new array with a separator placed between adjacent items. + +- separator: any (positional) + The value to insert between each item of the array. + ### sorted() Return a new array with the same items, but sorted. diff --git a/tests/typ/compiler/array.typ b/tests/typ/compiler/array.typ index e2463cb0e..96c6c668f 100644 --- a/tests/typ/compiler/array.typ +++ b/tests/typ/compiler/array.typ @@ -216,6 +216,13 @@ // Ref: true #([One], [Two], [Three]).join([, ], last: [ and ]). +--- +// Test the `intersperse` method +#test(().intersperse("a"), ()) +#test((1,).intersperse("a"), (1,)) +#test((1, 2).intersperse("a"), (1, "a", 2)) +#test((1, 2, "b").intersperse("a"), (1, "a", 2, "a", "b")) + --- // Test the `sorted` method. #test(().sorted(), ())