Skip to content

Commit

Permalink
add @array.zip and @array.zip_with
Browse files Browse the repository at this point in the history
  • Loading branch information
myfreess committed Jan 26, 2025
1 parent 9e073ba commit 01aafb4
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
63 changes: 63 additions & 0 deletions array/array.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,69 @@ pub fn last[A](self : Array[A]) -> A? {
}
}

///| Zips two arrays into a single array of tuples.
///
/// Parameters:
///
/// * `l` : The first array.
/// * `r` : The second array.
///
/// Returns an array of tuples, where each tuple contains corresponding elements
/// from the two input arrays.
///
/// Example:
///
/// ```moonbit
/// test "zip" {
/// let arr1 = [1, 2, 3]
/// let arr2 = ['a', 'b', 'c']
/// inspect!(zip(arr1, arr2), content="[(1, 'a'), (2, 'b'), (3, 'c')]")
/// }
/// ```
pub fn zip[A, B](l : Array[A], r : Array[B]) -> Array[(A, B)] {
let length = if l.length() < r.length() { l.length() } else { r.length() }
let arr = Array::new(capacity=length)
for i = 0; i < length; i = i + 1 {
arr.push((l[i], r[i]))
} else {
return arr
}
}

///| Zips two arrays into a single array by applying a function to each pair of elements.
///
/// Parameters:
///
/// * `l` : The first array.
/// * `r` : The second array.
/// * `merge` : A function that takes two arguments, one from each array, and returns a value.
///
/// Returns an array containing the results of applying the function to each pair of elements.
///
/// Example:
///
/// ```moonbit
/// test "zip_with" {
/// let arr1 = [1, 2, 3]
/// let arr2 = [4, 5, 6]
/// let add = fn(a, b) { a + b }
/// inspect!(zip_with(arr1, arr2, merge=add), content="[5, 7, 9]")
/// }
/// ```
pub fn zip_with[A, B, C](
l : Array[A],
r : Array[B],
merge~ : (A, B) -> C
) -> Array[C] {
let length = if l.length() < r.length() { l.length() } else { r.length() }
let arr = Array::new(capacity=length)
for i = 0; i < length; i = i + 1 {
arr.push(merge(l[i], r[i]))
} else {
return arr
}
}

///|
pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] with arbitrary(
size,
Expand Down
3 changes: 3 additions & 0 deletions array/array.mbti
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package moonbitlang/core/array
alias @moonbitlang/core/quickcheck as @quickcheck

// Values
fn zip[A, B](Array[A], Array[B]) -> Array[(A, B)]

fn zip_with[A, B, C](Array[A], Array[B], merge~ : (A, B) -> C) -> Array[C]

// Types and methods
impl FixedArray {
Expand Down
40 changes: 40 additions & 0 deletions array/array_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,46 @@ test "Array::last" {
inspect!([1].last(), content="Some(1)")
}

test "zip" {
// Test with two non-empty arrays
let arr1 = [1, 2, 3]
let arr2 = ['a', 'b', 'c']
inspect!(zip(arr1, arr2), content="[(1, 'a'), (2, 'b'), (3, 'c')]")

// Test with arrays of different lengths
let arr3 = [1, 2]
let arr4 = ["a", "b", "c"]
inspect!(
zip(arr3, arr4),
content=
#|[(1, "a"), (2, "b")]
,
)

// Test with an empty array
let arr5 : Array[Int] = []
let arr6 = ["a", "b", "c"]
inspect!(zip(arr5, arr6), content="[]")
}

test "zip_with" {
// Test with two non-empty arrays and a function
let arr1 = [1, 2, 3]
let arr2 = [4, 5, 6]
let add = fn(a, b) { a + b }
inspect!(zip_with(arr1, arr2, merge=add), content="[5, 7, 9]")

// Test with arrays of different lengths and a function
let arr3 = [1, 2]
let arr4 = [4, 5, 6]
inspect!(zip_with(arr3, arr4, merge=add), content="[5, 7]")

// Test with an empty array and a function
let arr5 : Array[Int] = []
let arr6 = [4, 5, 6]
inspect!(zip_with(arr5, arr6, merge=add), content="[]")
}

test "arbitrary" {
let arr : Array[Array[Int]] = @quickcheck.samples(20)
inspect!(arr[5:9], content="[[0], [0], [0], [0, 0, 0]]")
Expand Down

0 comments on commit 01aafb4

Please sign in to comment.