Allow integers for take and drop. (#3854)

Allows passing an integer to take or drop as a shorthand.
This commit is contained in:
James Dunkerley 2022-11-04 14:03:28 +00:00 committed by GitHub
parent 20cfea8422
commit b5881efdf0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 94 additions and 18 deletions

View File

@ -149,8 +149,9 @@ sort_and_merge_ranges ranges =
the method wants to work only with normalized ranges, it must perform
normalization on its own.
- range: The `Index_Sub_Range` to take from the collection.
take_helper : Integer -> (Integer -> Any) -> (Integer -> Integer -> Any) -> (Vector (Integer | Range) -> Vector Any) -> Index_Sub_Range -> Any
take_helper : Integer -> (Integer -> Any) -> (Integer -> Integer -> Any) -> (Vector (Integer | Range) -> Vector Any) -> (Index_Sub_Range | Range | Integer) -> Any
take_helper length at single_slice slice_ranges index_sub_range = case index_sub_range of
count : Integer -> take_helper length at single_slice slice_ranges (First count)
Range_Data _ _ _ -> take_helper length at single_slice slice_ranges (By_Index index_sub_range)
First count -> single_slice 0 (Math.min length count)
Last count -> single_slice length-count length
@ -198,8 +199,9 @@ take_helper length at single_slice slice_ranges index_sub_range = case index_sub
in the provided order. The function may assume that the ranges have been
normalized.
- range: The `Index_Sub_Range` to drop from the collection.
drop_helper : Integer -> (Integer -> Any) -> (Integer -> Integer -> Any) -> (Vector (Integer | Range) -> Vector Any) -> Index_Sub_Range -> Any
drop_helper : Integer -> (Integer -> Any) -> (Integer -> Integer -> Any) -> (Vector (Integer | Range) -> Vector Any) -> (Index_Sub_Range | Range | Integer) -> Any
drop_helper length at single_slice slice_ranges index_sub_range = case index_sub_range of
_ : Integer -> single_slice index_sub_range length
Range_Data _ _ _ -> drop_helper length at single_slice slice_ranges (By_Index index_sub_range)
First count -> single_slice count length
Last count -> single_slice 0 length-count

View File

@ -1086,7 +1086,7 @@ Text.repeat self count=1 =
"Hello World!".take (By_Index [1, 0, 0, 6, 0]) == "eHHWH"
"Hello World!".take (By_Index [Range 0 3, 6, Range 6 12 2]) == "HelWWrd"
"Hello World!".take (Sample 3 seed=42) == "l d"
Text.take : (Text_Sub_Range | Index_Sub_Range | Range) -> Text ! Index_Out_Of_Bounds_Error
Text.take : (Text_Sub_Range | Index_Sub_Range | Range | Integer) -> Text ! Index_Out_Of_Bounds_Error
Text.take self range=(First 1) =
ranges = Text_Sub_Range.find_codepoint_ranges self range
case ranges of

View File

@ -44,7 +44,7 @@ type Text_Sub_Range
While the input ranges may have varying steps, they are processed and split
in such a way that the ranges returned by this method always have a step
equal to 1.
find_codepoint_ranges : Text -> (Text_Sub_Range | Index_Sub_Range | Range) -> (Range_Data | Codepoint_Ranges)
find_codepoint_ranges : Text -> (Text_Sub_Range | Index_Sub_Range | Range | Integer) -> (Range_Data | Codepoint_Ranges)
find_codepoint_ranges text subrange =
case subrange of
Before delimiter ->
@ -103,6 +103,8 @@ find_codepoint_ranges text subrange =
find_codepoint_ranges text (By_Index range)
Range_Data _ _ _ ->
find_codepoint_ranges text (By_Index subrange)
_ : Integer ->
find_codepoint_ranges text (First subrange)
# TODO Dubious constructor export
from project.Data.Text.Text_Sub_Range.Codepoint_Ranges import all

View File

@ -656,7 +656,7 @@ type Vector a
If an `Index_Sub_Range`, then the selection is interpreted following
the rules of that type.
If a `Range`, the selection is specified by two indices, from and to.
take : (Index_Sub_Range | Range) -> Vector Any
take : (Index_Sub_Range | Range | Integer) -> Vector Any
take self range=(First 1) = case range of
## We are using a specialized implementation for `take Sample`, because
the default implementation (which needs to be generic for any
@ -675,7 +675,7 @@ type Vector a
If an `Index_Sub_Range`, then the selection is interpreted following
the rules of that type.
If a `Range`, the selection is specified by two indices, from and to.
drop : (Index_Sub_Range | Range) -> Vector Any
drop : (Index_Sub_Range | Range | Integer) -> Vector Any
drop self range=(First 1) =
Index_Sub_Range.drop_helper self.length (self.at _) self.slice (slice_ranges self) range

View File

@ -573,7 +573,7 @@ type Column
Arguments:
- range: The selection of rows from the table to return.
take : (Index_Sub_Range | Range) -> Column
take : (Index_Sub_Range | Range | Integer) -> Column
take self range=(First 1) =
_ = range
msg = "`Column.take` is not yet implemented."
@ -585,7 +585,7 @@ type Column
Arguments:
- range: The selection of rows from the table to remove.
drop : (Index_Sub_Range | Range) -> Column
drop : (Index_Sub_Range | Range | Integer) -> Column
drop self range=(First 1) =
_ = range
msg = "`Column.drop` is not yet implemented."

View File

@ -413,7 +413,7 @@ type Table
Arguments:
- range: The selection of rows from the table to return.
take : (Index_Sub_Range | Range) -> Table
take : (Index_Sub_Range | Range | Integer) -> Table
take self range=(First 1) =
_ = range
msg = "`Table.take` is not yet implemented."
@ -426,7 +426,7 @@ type Table
Arguments:
- range: The selection of rows from the table to remove.
drop : (Index_Sub_Range | Range) -> Table
drop : (Index_Sub_Range | Range | Integer) -> Table
drop self range=(First 1) =
_ = range
msg = "`Table.drop` is not yet implemented."

View File

@ -1143,7 +1143,7 @@ type Column
Arguments:
- range: The selection of rows from the table to return.
take : (Index_Sub_Range | Range) -> Column
take : (Index_Sub_Range | Range | Integer) -> Column
take self range=(First 1) =
Index_Sub_Range.take_helper self.length self.at self.slice (slice_ranges self) range
@ -1152,7 +1152,7 @@ type Column
Arguments:
- range: The selection of rows from the table to remove.
drop : (Index_Sub_Range | Range) -> Column
drop : (Index_Sub_Range | Range | Integer) -> Column
drop self range=(First 1) =
Index_Sub_Range.drop_helper self.length self.at self.slice (slice_ranges self) range

View File

@ -890,7 +890,7 @@ type Table
Take rows from the top of the table as long as their values sum to 10.
table.take (While row-> row.to_vector.sum == 10)
take : (Index_Sub_Range | Range) -> Table
take : (Index_Sub_Range | Range | Integer) -> Table
take self range=(First 1) =
Index_Sub_Range.take_helper self.row_count self.rows.at self.slice (slice_ranges self) range
@ -912,7 +912,7 @@ type Table
Drop rows from the top of the table as long as their values sum to 10.
table.drop (While row-> row.to_vector.sum == 10)
drop : (Index_Sub_Range | Range) -> Table
drop : (Index_Sub_Range | Range | Integer) -> Table
drop self range=(First 1) =
Index_Sub_Range.drop_helper self.row_count self.rows.at self.slice (slice_ranges self) range

View File

@ -37,6 +37,14 @@ spec = Test.group "Columns" <|
test_column.take (First 7) . to_vector . should_equal expected_2.to_vector
test_column.take (First 0) . to_vector . should_equal expected_3.to_vector
Test.specify "should be able to take the first n elements by Integer" <|
expected_1 = Column.from_vector "Test" [1, 3, 5]
expected_2 = Column.from_vector "Test" [1, 3, 5, 2, 4, 6]
expected_3 = Column.from_vector "Test" []
test_column.take 3 . to_vector . should_equal expected_1.to_vector
test_column.take 7 . to_vector . should_equal expected_2.to_vector
test_column.take 0 . to_vector . should_equal expected_3.to_vector
Test.specify "should be able to take the last n elements" <|
expected_1 = Column.from_vector "Test" [2, 4, 6]
expected_2 = Column.from_vector "Test" [1, 3, 5, 2, 4, 6]

View File

@ -815,6 +815,16 @@ spec prefix table_builder test_selection pending=Nothing =
table.drop (First -1) . should_equal table
table.drop (First 100) . should_equal empty
table.take 4 . at "alpha" . to_vector . should_equal [1,2,3,4]
table.take 0 . at "alpha" . to_vector . should_equal []
table.take -1 . at "alpha" . to_vector . should_equal []
table.take 100 . should_equal table
table.drop 2 . at "beta" . to_vector . should_equal ["C","D","E","F","G","H"]
table.drop 0 . should_equal table
table.drop -1 . should_equal table
table.drop 100 . should_equal empty
table.take (Last 4) . at "beta" . to_vector . should_equal ["E","F","G","H"]
table.take (Last 0) . should_equal empty
table.take (Last -1) . should_equal empty
@ -940,11 +950,21 @@ spec prefix table_builder test_selection pending=Nothing =
alpha.take (First -1) . should_equal empty_alpha
alpha.take (First 100) . should_equal alpha
alpha.take 4 . to_vector . should_equal [1,2,3,4]
alpha.take 0 . should_equal empty_alpha
alpha.take -1 . should_equal empty_alpha
alpha.take 100 . should_equal alpha
beta.drop (First 2) . to_vector . should_equal ["C","D","E","F","G","H"]
alpha.drop (First 0) . should_equal alpha
alpha.drop (First -1) . should_equal alpha
alpha.drop (First 100) . should_equal empty_alpha
beta.drop 2 . to_vector . should_equal ["C","D","E","F","G","H"]
alpha.drop 0 . should_equal alpha
alpha.drop -1 . should_equal alpha
alpha.drop 100 . should_equal empty_alpha
beta.take (Last 4) . to_vector . should_equal ["E","F","G","H"]
beta.take (Last 0) . should_equal empty_beta
beta.take (Last -1) . should_equal empty_beta
@ -1022,11 +1042,17 @@ spec prefix table_builder test_selection pending=Nothing =
Test.specify "should allow sampling rows" <|
three = table_builder [["X", ["a", "a", "a"]]] . at "X"
two = three.take (First 2)
one = three.take First
empty = three.take (First 0)
two = table_builder [["X", ["a", "a"]]] . at "X"
one = table_builder [["X", ["a"]]] . at "X"
empty = table_builder [["X", []]] . at "X"
[three, two, one, empty].map .to_vector . should_equal [["a", "a", "a"], ["a", "a"], ["a"], []]
three.take (First 2) . should_equal two
three.take First . should_equal one
three.take (First 0) . should_equal empty
three.take 2 . should_equal two
three.take . should_equal one
three.take 0 . should_equal empty
three.take (Sample 0) . should_equal empty
empty.take (Sample 0) . should_equal empty

View File

@ -622,6 +622,7 @@ spec =
t_1 = Table.new [i_1, c_1, c_2, c_3] . set_index 'ix'
t_1.take (First 10) . at 'col' . to_vector . should_equal (t_1.at 'col' . to_vector)
t_1.take 10 . at 'col' . to_vector . should_equal (t_1.at 'col' . to_vector)
t_2 = t_1.take (First 2)
t_2.index.to_vector . should_equal (t_1.index.to_vector . take (First 2))
@ -629,7 +630,14 @@ spec =
t_2.at 'col2' . to_vector . should_equal (t_1.at 'col2' . to_vector . take (First 2))
t_2.at 'col3' . to_vector . should_equal (t_1.at 'col3' . to_vector . take (First 2))
t_3 = t_1.take 2
t_3.index.to_vector . should_equal (t_1.index.to_vector . take 2)
t_3.at 'col' . to_vector . should_equal (t_1.at 'col' . to_vector . take 2)
t_3.at 'col2' . to_vector . should_equal (t_1.at 'col2' . to_vector . take 2)
t_3.at 'col3' . to_vector . should_equal (t_1.at 'col3' . to_vector . take 2)
t_1.at 'col' . take (First 2) . to_vector . should_equal (t_1.at 'col' . to_vector . take (First 2))
t_1.at 'col' . take 2 . to_vector . should_equal (t_1.at 'col' . to_vector . take 2)
Test.specify "should allow taking the last n rows" <|
i_1 = ['ix', [1, 2, 3]]

View File

@ -325,6 +325,8 @@ spec =
txt = kshi + facepalm + accent_1 + accent_2
txt.take (First 2) . should_equal (kshi + facepalm)
txt.drop (First 2) . should_equal (accent_1 + accent_2)
txt.take 2 . should_equal (kshi + facepalm)
txt.drop 2 . should_equal (accent_1 + accent_2)
txt.take (Last 2) . should_equal (accent_1 + accent_2)
txt.drop (Last 2) . should_equal (kshi + facepalm)
txt.take (Range_Data 0 2) . should_equal (kshi + facepalm)
@ -353,6 +355,10 @@ spec =
"Hello World!".take (First 5) . should_equal "Hello"
"Hello World!".take (First 100) . should_equal "Hello World!"
"Hello World!".take (First 0) . should_equal ""
"Hello World!".take . should_equal "H"
"Hello World!".take 5 . should_equal "Hello"
"Hello World!".take 100 . should_equal "Hello World!"
"Hello World!".take 0 . should_equal ""
"Hello World!".take Last . should_equal "!"
"Hello World!".take (Last 6) . should_equal "World!"
"Hello World!".take (Last 0) . should_equal ""
@ -386,6 +392,7 @@ spec =
txt.take (Range_Data txt.length txt.length) . catch . should_equal (Index_Out_Of_Bounds_Error_Data txt.length txt.length)
txt.take (Range_Data txt.length 100) . should_fail_with Index_Out_Of_Bounds_Error_Data
txt.take (First 100) . should_equal txt
txt.take 100 . should_equal txt
txt.take (Last 100) . should_equal txt
txt.take (By_Index 100) . should_fail_with Index_Out_Of_Bounds_Error_Data
txt.take (By_Index 13) . should_fail_with Index_Out_Of_Bounds_Error_Data
@ -413,6 +420,8 @@ spec =
txt_1.take (Every 2) . should_equal 'Hlo\u0308Wrd'
txt_1.take (First 2) . should_equal 'He\u{302}'
txt_1.take (First 5) . should_equal 'He\u{302}llo\u{308}'
txt_1.take 2 . should_equal 'He\u{302}'
txt_1.take 5 . should_equal 'He\u{302}llo\u{308}'
txt_1.take (Last 6) . should_equal 'Wo\u{301}rld!'
txt_1.take (Last 5) . should_equal 'o\u{301}rld!'
txt_1.take (Before 'e\u{302}') . should_equal 'H'
@ -437,6 +446,8 @@ spec =
Test.specify "take should work on emojis" <|
'✨🚀🚧😍😃😎😙😉☺'.take First . should_equal '✨'
'✨🚀🚧😍😃😎😙😉☺'.take (First 2) . should_equal '✨🚀'
'✨🚀🚧😍😃😎😙😉☺'.take . should_equal '✨'
'✨🚀🚧😍😃😎😙😉☺'.take 2 . should_equal '✨🚀'
'✨🚀🚧😍😃😎😙😉☺'.take Last . should_equal '☺'
'✨🚀🚧😍😃😎😙😉☺'.take (Last 0) . should_equal ''
'✨🚀🚧😍😃😎😙😉☺'.take (Last 3) . should_equal '😙😉☺'
@ -489,6 +500,10 @@ spec =
"Hello World!".drop (First 5) . should_equal " World!"
"Hello World!".drop (First 100) . should_equal ""
"Hello World!".drop (First 0) . should_equal "Hello World!"
"Hello World!".drop . should_equal "ello World!"
"Hello World!".drop 5 . should_equal " World!"
"Hello World!".drop 100 . should_equal ""
"Hello World!".drop 0 . should_equal "Hello World!"
"Hello World!".drop Last . should_equal "Hello World"
"Hello World!".drop (Last 6) . should_equal "Hello "
"Hello World!".drop (Last 100) . should_equal ""
@ -516,6 +531,7 @@ spec =
txt = "Hello World!"
txt.drop (Range_Data 0 14) . should_equal ""
txt.drop (First 100) . should_equal ""
txt.drop 100 . should_equal ""
txt.drop (Last 100) . should_equal ""
txt.drop (By_Index 100) . should_fail_with Index_Out_Of_Bounds_Error_Data
txt.drop (By_Index 100) . catch . should_equal (Index_Out_Of_Bounds_Error_Data 100 12)
@ -539,6 +555,8 @@ spec =
txt_1.drop (Every 2) . should_equal 'e\u0302l o\u0301l!'
txt_1.drop (First 2) . should_equal 'llo\u{308} Wo\u{301}rld!'
txt_1.drop (First 5) . should_equal ' Wo\u{301}rld!'
txt_1.drop 2 . should_equal 'llo\u{308} Wo\u{301}rld!'
txt_1.drop 5 . should_equal ' Wo\u{301}rld!'
txt_1.drop (Last 6) . should_equal 'He\u{302}llo\u{308} '
txt_1.drop (Last 5) . should_equal 'He\u{302}llo\u{308} W'
txt_1.drop (Before 'e\u{302}') . should_equal 'e\u{302}llo\u{308} Wo\u{301}rld!'
@ -563,6 +581,8 @@ spec =
Test.specify "drop should work on emojis" <|
'✨🚀🚧😍😃😎😙😉☺'.drop First . should_equal '🚀🚧😍😃😎😙😉☺'
'✨🚀🚧😍😃😎😙😉☺'.drop (First 2) . should_equal '🚧😍😃😎😙😉☺'
'✨🚀🚧😍😃😎😙😉☺'.drop . should_equal '🚀🚧😍😃😎😙😉☺'
'✨🚀🚧😍😃😎😙😉☺'.drop 2 . should_equal '🚧😍😃😎😙😉☺'
'✨🚀🚧😍😃😎😙😉☺'.drop Last . should_equal '✨🚀🚧😍😃😎😙😉'
'✨🚀🚧😍😃😎😙😉☺'.drop (Last 3) . should_equal '✨🚀🚧😍😃😎'
'✨🚀🚧😍😃😍😎😙😉☺'.drop (Before '😍') . should_equal '😍😃😍😎😙😉☺'

View File

@ -335,6 +335,16 @@ spec = Test.group "Vectors" <|
vec.drop (First -1) . should_equal vec
vec.drop (First 100) . should_equal []
vec.take 4 . should_equal first_four
vec.take 0 . should_equal []
vec.take -1 . should_equal []
vec.take 100 . should_equal vec
vec.drop 2 . should_equal last_four
vec.drop 0 . should_equal vec
vec.drop -1 . should_equal vec
vec.drop 100 . should_equal []
vec.take (Last 4) . should_equal last_four
vec.take (Last 0) . should_equal []
vec.take (Last -1) . should_equal []