diff --git a/src/data_structures/src/array_ext.cairo b/src/data_structures/src/array_ext.cairo index e6ab14d7..a1420a3c 100644 --- a/src/data_structures/src/array_ext.cairo +++ b/src/data_structures/src/array_ext.cairo @@ -21,6 +21,7 @@ trait ArrayTraitExt { fn index_of_max, impl TPartialOrd: PartialOrd>( self: @Array ) -> Option; + fn dedup>(self: @Array) -> Array; } trait SpanTraitExt { @@ -43,6 +44,7 @@ trait SpanTraitExt { fn index_of_max, impl TPartialOrd: PartialOrd>( self: Span ) -> Option; + fn dedup>(self: Span) -> Array; } impl ArrayImpl, impl TDrop: Drop> of ArrayTraitExt { @@ -135,6 +137,10 @@ impl ArrayImpl, impl TDrop: Drop> of ArrayTraitExt ) -> Option { self.span().index_of_max() } + + fn dedup>(mut self: @Array) -> Array { + self.span().dedup() + } } impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { @@ -354,4 +360,29 @@ impl SpanImpl, impl TDrop: Drop> of SpanTraitExt { index += 1; } } + + fn dedup>(mut self: Span) -> Array { + if self.len() == 0 { + return array![]; + } + + let mut last_value = self.pop_front().unwrap(); + let mut ret = array![*last_value]; + + loop { + match self.pop_front() { + Option::Some(v) => { + if (last_value != v) { + last_value = v; + ret.append(*v); + }; + }, + Option::None => { + break; + } + }; + }; + + ret + } } diff --git a/src/data_structures/src/tests/array_ext_test.cairo b/src/data_structures/src/tests/array_ext_test.cairo index 9ed7fd0f..e4f95426 100644 --- a/src/data_structures/src/tests/array_ext_test.cairo +++ b/src/data_structures/src/tests/array_ext_test.cairo @@ -3,6 +3,111 @@ use array::{ArrayTrait, SpanTrait}; use alexandria_data_structures::array_ext::{ArrayTraitExt, SpanTraitExt}; +// dedup + +#[test] +#[available_gas(2000000)] +fn dedup_all_different() { + let mut destination = array![1, 2, 3, 4]; + let new_arr = destination.dedup(); + let len = new_arr.len(); + + assert(*new_arr[0] == 1, 'Should be 1'); + assert(*new_arr[1] == 2, 'Should be 2'); + assert(*new_arr[2] == 3, 'Should be 3'); + assert(*new_arr[3] == 4, 'Should be 4'); + assert(new_arr.len() == 4, 'Len should be 4'); +} + +#[test] +#[available_gas(2000000)] +fn dedup_one_match() { + let mut destination = array![1, 2, 2, 3, 4]; + let new_arr = destination.dedup(); + let len = new_arr.len(); + + assert(*new_arr[0] == 1, 'Should be 1'); + assert(*new_arr[1] == 2, 'Should be 2'); + assert(*new_arr[2] == 3, 'Should be 3'); + assert(*new_arr[3] == 4, 'Should be 4'); + assert(new_arr.len() == 4, 'Len should be 4'); +} + +#[test] +#[available_gas(2000000)] +fn dedup_two_matches() { + let mut destination = array![1, 2, 2, 3, 4, 4]; + let new_arr = destination.dedup(); + let len = new_arr.len(); + + assert(*new_arr[0] == 1, 'Should be 1'); + assert(*new_arr[1] == 2, 'Should be 2'); + assert(*new_arr[2] == 3, 'Should be 3'); + assert(*new_arr[3] == 4, 'Should be 4'); + assert(new_arr.len() == 4, 'Len should be 4'); +} + +#[test] +#[available_gas(2000000)] +fn dedup_one_match_more() { + let mut destination = array![1, 2, 2, 2, 3, 4, 4]; + let new_arr = destination.dedup(); + let len = new_arr.len(); + + assert(*new_arr[0] == 1, 'Should be 1'); + assert(*new_arr[1] == 2, 'Should be 2'); + assert(*new_arr[2] == 3, 'Should be 3'); + assert(*new_arr[3] == 4, 'Should be 4'); + assert(new_arr.len() == 4, 'Len should be 4'); +} + +#[test] +#[available_gas(2000000)] +fn dedup_all_same() { + let mut destination = array![2, 2, 2, 2]; + let new_arr = destination.dedup(); + let len = new_arr.len(); + + assert(*new_arr[0] == 2, 'Should be 2'); + assert(new_arr.len() == 1, 'Len should be 1'); +} + +#[test] +#[available_gas(2000000)] +fn dedup_one_elem() { + let mut destination = array![2]; + let new_arr = destination.dedup(); + let len = new_arr.len(); + + assert(*new_arr[0] == 2, 'Should be 2'); + assert(new_arr.len() == 1, 'Len should be 1'); +} + +#[test] +#[available_gas(2000000)] +fn dedup_no_elem() { + let mut destination = ArrayTrait::::new(); + let new_arr = destination.dedup(); + let len = new_arr.len(); + assert(new_arr.len() == 0, 'Len should be 0'); +} + +#[test] +#[available_gas(2000000)] +fn dedup_multiple_duplicates_same() { + let mut destination = array![1, 1, 3, 4, 3, 3, 3, 4, 2, 2]; + let new_arr = destination.dedup(); + let len = new_arr.len(); + + assert(new_arr.len() == 6, 'Len should be 6'); + assert(*new_arr[0] == 1, 'Should be 1'); + assert(*new_arr[1] == 3, 'Should be 3'); + assert(*new_arr[2] == 4, 'Should be 4'); + assert(*new_arr[3] == 3, 'Should be 3'); + assert(*new_arr[4] == 4, 'Should be 4'); + assert(*new_arr[5] == 2, 'Should be 2'); +} + // append_all #[test]