mirror of
https://github.com/enso-org/enso.git
synced 2024-11-23 08:08:34 +03:00
Short hand version for order_by
(#3643)
Implements https://www.pivotaltracker.com/story/show/182868310
This commit is contained in:
parent
146297a0a0
commit
fbf6c800f1
@ -176,6 +176,7 @@
|
||||
`Text.drop`.][3617]
|
||||
- [Updated `Vector.take` and `Vector.drop` and removed their obsolete
|
||||
counterparts.][3629]
|
||||
- [Short-hand syntax for `order_by` added.][3643]
|
||||
|
||||
[debug-shortcuts]:
|
||||
https://github.com/enso-org/enso/blob/develop/app/gui/docs/product/shortcuts.md#debug
|
||||
@ -276,6 +277,7 @@
|
||||
[3601]: https://github.com/enso-org/enso/pull/3601
|
||||
[3617]: https://github.com/enso-org/enso/pull/3617
|
||||
[3629]: https://github.com/enso-org/enso/pull/3629
|
||||
[3643]: https://github.com/enso-org/enso/pull/3643
|
||||
[3648]: https://github.com/enso-org/enso/pull/3648
|
||||
|
||||
#### Enso Compiler
|
||||
|
@ -472,21 +472,10 @@ type Table
|
||||
|
||||
Missing (`Nothing`) values are sorted as less than any other object.
|
||||
|
||||
> Example
|
||||
Order the table by the column "alpha" in ascending order.
|
||||
|
||||
table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "alpha"])
|
||||
|
||||
> Example
|
||||
Order the table by the second column in ascending order. In case of any
|
||||
ties, break them based on the 7th column from the end of the table in
|
||||
descending order.
|
||||
|
||||
table.order_by (Sort_Column_Selector.By_Index [Sort_Column.Index 1, Sort_Column.Index -7 Sort_Direction.Descending])
|
||||
> Example
|
||||
Sorting `table` in ascending order by the value in column `'Quantity'`.
|
||||
|
||||
table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'Quantity'])
|
||||
table.order_by (Sort_Column_Selector.By_Name ['Quantity'])
|
||||
|
||||
> Example
|
||||
Sorting `table` in descending order by the value in column `'Quantity'`.
|
||||
@ -497,7 +486,7 @@ type Table
|
||||
Sorting `table` in ascending order by the value in column `'Quantity'`,
|
||||
using the value in column `'Rating'` for breaking ties.
|
||||
|
||||
table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'Quantity', Sort_Column.Name 'Rating'])
|
||||
table.order_by (Sort_Column_Selector.By_Name ['Quantity', 'Rating'])
|
||||
|
||||
> Example
|
||||
Sorting `table` in ascending order by the value in column `'Quantity'`,
|
||||
@ -505,6 +494,12 @@ type Table
|
||||
ties.
|
||||
|
||||
table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'Quantity', Sort_Column.Name 'Rating' Sort_Direction.Descending])
|
||||
> Example
|
||||
Order the table by the second column in ascending order. In case of any
|
||||
ties, break them based on the 7th column from the end of the table in
|
||||
descending order.
|
||||
|
||||
table.order_by (Sort_Column_Selector.By_Index [1, Sort_Column.Index -7 Sort_Direction.Descending])
|
||||
order_by : Sort_Column_Selector -> Text_Ordering -> Problem_Behavior -> Table
|
||||
order_by self (columns = (Sort_Column_Selector.By_Name [(Sort_Column.Name (self.columns.at 0 . name))])) text_ordering=Text_Ordering on_problems=Report_Warning = Panic.handle_wrapped_dataflow_error <|
|
||||
problem_builder = Problem_Builder.new
|
||||
|
@ -3,6 +3,6 @@ from Standard.Base import all
|
||||
import Standard.Table.Data.Sort_Column
|
||||
|
||||
type Sort_Column_Selector
|
||||
type By_Name (columns : Vector Sort_Column.Name) (matcher:Matcher=Text_Matcher)
|
||||
type By_Index (columns : Vector Sort_Column.Index)
|
||||
type By_Column (columns : Vector Sort_Column.Column)
|
||||
type By_Name (columns : Vector (Sort_Column.Name | Text)) (matcher:Matcher=Text_Matcher)
|
||||
type By_Index (columns : Vector (Sort_Column.Index | Integer))
|
||||
type By_Column (columns : Vector (Sort_Column.Column | Column))
|
||||
|
@ -560,23 +560,42 @@ type Table
|
||||
`Incomparable_Values_Error`.
|
||||
|
||||
> Example
|
||||
Order the table by the column "alpha" in ascending order.
|
||||
Sorting `table` in ascending order by the value in column `'Quantity'`.
|
||||
|
||||
table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "alpha"])
|
||||
table.order_by (Sort_Column_Selector.By_Name ['Quantity'])
|
||||
|
||||
> Example
|
||||
Sorting `table` in descending order by the value in column `'Quantity'`.
|
||||
|
||||
table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'Quantity' Sort_Direction.Descending])
|
||||
|
||||
> Example
|
||||
Sorting `table` in ascending order by the value in column `'Quantity'`,
|
||||
using the value in column `'Rating'` for breaking ties.
|
||||
|
||||
table.order_by (Sort_Column_Selector.By_Name ['Quantity', 'Rating'])
|
||||
|
||||
> Example
|
||||
Sorting `table` in ascending order by the value in column `'Quantity'`,
|
||||
using the value in column `'Rating'` in descending order for breaking
|
||||
ties.
|
||||
|
||||
table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'Quantity', Sort_Column.Name 'Rating' Sort_Direction.Descending])
|
||||
|
||||
> Example
|
||||
Order the table by the second column in ascending order. In case of any
|
||||
ties, break them based on the 7th column from the end of the table in
|
||||
descending order.
|
||||
|
||||
table.order_by (Sort_Column_Selector.By_Index [Sort_Column.Index 1, Sort_Column.Index -7 Sort_Direction.Descending])
|
||||
table.order_by (Sort_Column_Selector.By_Index [1, Sort_Column.Index -7 Sort_Direction.Descending])
|
||||
|
||||
> Example
|
||||
Sorting the shop inventory based on the per-item price in ascending
|
||||
order.
|
||||
|
||||
import Standard.Examples
|
||||
|
||||
example_sort = Examples.inventory_table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "price"])
|
||||
example_sort = Examples.inventory_table.order_by (Sort_Column_Selector.By_Name ["price"])
|
||||
|
||||
> Example
|
||||
Sort the shop inventory based on the per-item price in descending order
|
||||
@ -606,7 +625,7 @@ type Table
|
||||
|
||||
example_sort =
|
||||
table = Examples.inventory_table
|
||||
table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "total_stock", Sort_Column.Name "sold_stock" Sort_Direction.Descending])
|
||||
table.order_by (Sort_Column_Selector.By_Name ["total_stock", Sort_Column.Name "sold_stock" Sort_Direction.Descending])
|
||||
|
||||
order_by : Sort_Column_Selector -> Text_Ordering -> Problem_Behavior -> Table
|
||||
order_by self (columns = (Sort_Column_Selector.By_Name [(Sort_Column.Name (self.columns.at 0 . name))])) text_ordering=Text_Ordering on_problems=Report_Warning =
|
||||
|
@ -365,11 +365,23 @@ prepare_order_by : Vector -> Problem_Builder -> Vector Column_Transform_Element
|
||||
prepare_order_by internal_columns column_selectors problem_builder =
|
||||
selected_elements = case column_selectors of
|
||||
Sort_Column_Selector.By_Name name_selectors matcher ->
|
||||
select_columns_by_name internal_columns name_selectors matcher problem_builder name_extractor=(_.name)
|
||||
unified_name_selectors = name_selectors.map selector-> case selector of
|
||||
Text -> Sort_Column.Name selector
|
||||
Sort_Column.Name _ _ -> selector
|
||||
select_columns_by_name internal_columns unified_name_selectors matcher problem_builder name_extractor=(_.name)
|
||||
Sort_Column_Selector.By_Index index_selectors ->
|
||||
select_columns_by_index internal_columns index_selectors problem_builder index_extractor=(_.index)
|
||||
unified_index_selectors = index_selectors.map selector-> case selector of
|
||||
Integer -> Sort_Column.Index selector
|
||||
Sort_Column.Index _ _ -> selector
|
||||
select_columns_by_index internal_columns unified_index_selectors problem_builder index_extractor=(_.index)
|
||||
Sort_Column_Selector.By_Column column_selectors ->
|
||||
select_columns_by_column_reference internal_columns column_selectors problem_builder column_extractor=(_.column)
|
||||
unified_column_selectors = column_selectors.map selector-> case selector of
|
||||
Sort_Column.Column _ _ -> selector
|
||||
## We cannot match by type here, as there is no common `Column`
|
||||
type - the type is different for In-Memory and Database
|
||||
tables, and we do not have interfaces yet.
|
||||
column_reference -> Sort_Column.Column column_reference
|
||||
select_columns_by_column_reference internal_columns unified_column_selectors problem_builder column_extractor=(_.column)
|
||||
if selected_elements.is_empty then
|
||||
problem_builder.report_other_warning No_Input_Columns_Selected
|
||||
selected_elements
|
||||
|
@ -544,11 +544,11 @@ spec prefix table_builder test_selection pending=Nothing =
|
||||
table_builder [col1, col2, col3, col4, col5, col6, col7, col8, col9, col10]
|
||||
|
||||
Test.specify "should work as shown in the doc examples" <|
|
||||
t1 = table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "alpha"])
|
||||
t1 = table.order_by (Sort_Column_Selector.By_Name ["alpha"])
|
||||
t1.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
|
||||
t1.at "gamma" . to_vector . should_equal [4, 3, 2, 1]
|
||||
|
||||
t2 = table.order_by (Sort_Column_Selector.By_Index [Sort_Column.Index 1, Sort_Column.Index -8 Sort_Direction.Descending])
|
||||
t2 = table.order_by (Sort_Column_Selector.By_Index [1, Sort_Column.Index -8 Sort_Direction.Descending])
|
||||
t2.at "beta" . to_vector . should_equal ["a", "a", "b", "b"]
|
||||
t2.at "gamma" . to_vector . should_equal [3, 1, 4, 2]
|
||||
t2.at "alpha" . to_vector . should_equal [1, 3, 0, 2]
|
||||
@ -560,7 +560,7 @@ spec prefix table_builder test_selection pending=Nothing =
|
||||
t1.at "gamma" . to_vector . should_equal [2, 4, 3, 1]
|
||||
|
||||
Test.specify "should correctly handle problems: out of bounds indices" <|
|
||||
selector = Sort_Column_Selector.By_Index [Sort_Column.Index 0, Sort_Column.Index 100, Sort_Column.Index -200, Sort_Column.Index 300]
|
||||
selector = Sort_Column_Selector.By_Index [0, 100, Sort_Column.Index -200, Sort_Column.Index 300]
|
||||
action = table.order_by selector on_problems=_
|
||||
tester table =
|
||||
table.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
|
||||
@ -569,7 +569,7 @@ spec prefix table_builder test_selection pending=Nothing =
|
||||
Problems.test_problem_handling action problems tester
|
||||
|
||||
Test.specify "should correctly handle problems: duplicate indices" <|
|
||||
selector = Sort_Column_Selector.By_Index [Sort_Column.Index 0, Sort_Column.Index 0, Sort_Column.Index 0 Sort_Direction.Descending]
|
||||
selector = Sort_Column_Selector.By_Index [0, Sort_Column.Index 0, Sort_Column.Index 0 Sort_Direction.Descending]
|
||||
action = table.order_by selector on_problems=_
|
||||
tester table =
|
||||
table.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
|
||||
@ -578,7 +578,7 @@ spec prefix table_builder test_selection pending=Nothing =
|
||||
Problems.test_problem_handling action problems tester
|
||||
|
||||
Test.specify "should correctly handle problems: aliased indices" <|
|
||||
selector = Sort_Column_Selector.By_Index [Sort_Column.Index 1, Sort_Column.Index -9 Sort_Direction.Descending, Sort_Column.Index -8 Sort_Direction.Descending, Sort_Column.Index 2 Sort_Direction.Ascending]
|
||||
selector = Sort_Column_Selector.By_Index [1, Sort_Column.Index -9 Sort_Direction.Descending, Sort_Column.Index -8 Sort_Direction.Descending, Sort_Column.Index 2 Sort_Direction.Ascending]
|
||||
action = table.order_by selector on_problems=_
|
||||
tester table =
|
||||
table.at "beta" . to_vector . should_equal ["a", "a", "b", "b"]
|
||||
@ -588,7 +588,7 @@ spec prefix table_builder test_selection pending=Nothing =
|
||||
Problems.test_problem_handling action problems tester
|
||||
|
||||
Test.specify "should correctly handle problems: duplicate names" <|
|
||||
selector = Sort_Column_Selector.By_Name [Sort_Column.Name "alpha", Sort_Column.Name "alpha" Sort_Direction.Descending]
|
||||
selector = Sort_Column_Selector.By_Name ["alpha", Sort_Column.Name "alpha" Sort_Direction.Descending]
|
||||
action = table.order_by selector on_problems=_
|
||||
tester table =
|
||||
table.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
|
||||
@ -607,7 +607,7 @@ spec prefix table_builder test_selection pending=Nothing =
|
||||
|
||||
Test.specify "should correctly handle problems: unmatched names" <|
|
||||
weird_name = '.*?-!@#!"'
|
||||
selector = Sort_Column_Selector.By_Name [Sort_Column.Name "alpha", Sort_Column.Name "hmm", Sort_Column.Name weird_name]
|
||||
selector = Sort_Column_Selector.By_Name [Sort_Column.Name "alpha", "hmm", Sort_Column.Name weird_name]
|
||||
action = table.order_by selector on_problems=_
|
||||
tester table =
|
||||
table.at "alpha" . to_vector . should_equal [0, 1, 2, 3]
|
||||
@ -621,7 +621,7 @@ spec prefix table_builder test_selection pending=Nothing =
|
||||
weird_column = table_2.at "weird_column"
|
||||
bar = table.at "beta"
|
||||
|
||||
selector = Sort_Column_Selector.By_Column [Sort_Column.Column bar, Sort_Column.Column weird_column, Sort_Column.Column foo]
|
||||
selector = Sort_Column_Selector.By_Column [bar, weird_column, Sort_Column.Column foo]
|
||||
problem = table.order_by selector on_problems=Problem_Behavior.Report_Error . catch
|
||||
problem.should_be_a Missing_Input_Columns
|
||||
problem.criteria.map (selector-> selector.column.name) . should_equal ["weird_column"]
|
||||
@ -653,12 +653,12 @@ spec prefix table_builder test_selection pending=Nothing =
|
||||
t3.at "beta" . to_vector . should_equal ["a", "a", "b", "b"]
|
||||
t3.at "alpha" . to_vector . should_equal [1, 3, 0, 2]
|
||||
|
||||
t4 = t2.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "beta"])
|
||||
t4 = t2.order_by (Sort_Column_Selector.By_Name ["beta"])
|
||||
t4.at "beta" . to_vector . should_equal ["a", "a", "b", "b"]
|
||||
t4.at "alpha" . to_vector . should_equal [3, 1, 2, 0]
|
||||
|
||||
Test.specify "should give priority to the first selected column and use the next ones for breaking ties" <|
|
||||
t1 = table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "beta", Sort_Column.Name "alpha" Sort_Direction.Ascending])
|
||||
t1 = table.order_by (Sort_Column_Selector.By_Name ["beta", Sort_Column.Name "alpha" Sort_Direction.Ascending])
|
||||
t1.at "beta" . to_vector . should_equal ["a", "a", "b", "b"]
|
||||
t1.at "alpha" . to_vector . should_equal [1, 3, 0, 2]
|
||||
t1.at "gamma" . to_vector . should_equal [3, 1, 4, 2]
|
||||
@ -673,23 +673,23 @@ spec prefix table_builder test_selection pending=Nothing =
|
||||
t3.at "beta" . to_vector . should_equal ["b", "a", "b", "a"]
|
||||
t3.at "gamma" . to_vector . should_equal [4, 3, 2, 1]
|
||||
|
||||
t4 = table.order_by (Sort_Column_Selector.By_Index [Sort_Column.Index 1, Sort_Column.Index 0 Sort_Direction.Ascending])
|
||||
t4 = table.order_by (Sort_Column_Selector.By_Index [1, Sort_Column.Index 0 Sort_Direction.Ascending])
|
||||
t4.at "beta" . to_vector . should_equal ["a", "a", "b", "b"]
|
||||
t4.at "alpha" . to_vector . should_equal [1, 3, 0, 2]
|
||||
t4.at "gamma" . to_vector . should_equal [3, 1, 4, 2]
|
||||
|
||||
t5 = table.order_by (Sort_Column_Selector.By_Column [Sort_Column.Column (table.at "beta"), Sort_Column.Column (table.at "alpha") Sort_Direction.Ascending])
|
||||
t5 = table.order_by (Sort_Column_Selector.By_Column [table.at "beta", Sort_Column.Column (table.at "alpha") Sort_Direction.Ascending])
|
||||
t5.at "beta" . to_vector . should_equal ["a", "a", "b", "b"]
|
||||
t5.at "alpha" . to_vector . should_equal [1, 3, 0, 2]
|
||||
t5.at "gamma" . to_vector . should_equal [3, 1, 4, 2]
|
||||
|
||||
Test.specify "should deal with real numbers" <|
|
||||
t1 = table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "tau"])
|
||||
t1 = table.order_by (Sort_Column_Selector.By_Name ["tau"])
|
||||
t1.at "tau" . to_vector . should_equal [-0.1, 0.5, 1.6, 32.0]
|
||||
t1.at "alpha" . to_vector . should_equal [1, 2, 0, 3]
|
||||
|
||||
Test.specify "should deal with nulls" <|
|
||||
t1 = table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "xi"])
|
||||
t1 = table.order_by (Sort_Column_Selector.By_Name ["xi"])
|
||||
t1.at "xi" . to_vector . should_equal [Nothing, 0.5, 1.0, 1.5]
|
||||
t1.at "alpha" . to_vector . should_equal [1, 0, 3, 2]
|
||||
|
||||
@ -714,7 +714,7 @@ spec prefix table_builder test_selection pending=Nothing =
|
||||
t1.at "delta" . to_vector . should_equal ["a1", "a2", "a03", "a10"]
|
||||
t1.at "alpha" . to_vector . should_equal [2, 1, 0, 3]
|
||||
|
||||
t2 = table.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "delta"]) text_ordering=(Text_Ordering sort_digits_as_numbers=False)
|
||||
t2 = table.order_by (Sort_Column_Selector.By_Name ["delta"]) text_ordering=(Text_Ordering sort_digits_as_numbers=False)
|
||||
t2.at "delta" . to_vector . should_equal ["a03", "a1", "a10", "a2"]
|
||||
t2.at "alpha" . to_vector . should_equal [0, 2, 3, 1]
|
||||
|
||||
|
@ -335,32 +335,32 @@ spec =
|
||||
df = (enso_project.data / "clothes.csv").read
|
||||
|
||||
Test.specify "should allow sorting by a single column name" <|
|
||||
r_1 = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "Quantity"])
|
||||
r_1 = df.order_by (Sort_Column_Selector.By_Name ["Quantity"])
|
||||
r_1.at 'Id' . to_vector . should_equal [2,4,1,3,5,6]
|
||||
|
||||
r_3 = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "Rating" Sort_Direction.Descending])
|
||||
r_3.at 'Id' . to_vector . should_equal [3,1,4,5,2,6]
|
||||
|
||||
Test.specify 'should allow sorting by multiple column names' <|
|
||||
r_1 = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'Quantity', Sort_Column.Name 'Rating'])
|
||||
r_1 = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'Quantity', 'Rating'])
|
||||
r_1.at 'Id' . to_vector . should_equal [2,4,1,3,6,5]
|
||||
|
||||
r_2 = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'Rating' Sort_Direction.Descending, Sort_Column.Name 'Quantity' Sort_Direction.Descending])
|
||||
r_2.at 'Id' . to_vector . should_equal [3,1,4,5,6,2]
|
||||
|
||||
Test.specify 'should allow sorting with specific by-column rules' <|
|
||||
r_1 = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name "Quantity", Sort_Column.Name "Price" Sort_Direction.Descending])
|
||||
r_1 = df.order_by (Sort_Column_Selector.By_Name ["Quantity", Sort_Column.Name "Price" Sort_Direction.Descending])
|
||||
r_1.at 'Id' . to_vector . should_equal [4,2,3,1,6,5]
|
||||
|
||||
Test.specify 'should respect defined comparison operations for custom types' <|
|
||||
c_1 = ['id', [1, 2, 3, 4, 5, 6]]
|
||||
c_2 = ['val', [My 1 2, My 3 4, My 2 1, My 5 2, My 7 0, My 4 -1]]
|
||||
df = Table.new [c_1, c_2]
|
||||
r = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'val'])
|
||||
r = df.order_by (Sort_Column_Selector.By_Name ['val'])
|
||||
r.at 'id' . to_vector . should_equal [1,3,6,2,4,5]
|
||||
|
||||
Test.specify 'should return warnings and errors when passed a non-existent column' <|
|
||||
action = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'foobar']) on_problems=_
|
||||
action = df.order_by (Sort_Column_Selector.By_Name ['foobar']) on_problems=_
|
||||
tester table =
|
||||
table.at 'Id' . to_vector . should_equal [1,2,3,4,5,6]
|
||||
problems = [Missing_Input_Columns [Sort_Column.Name 'foobar'], No_Input_Columns_Selected]
|
||||
@ -375,7 +375,7 @@ spec =
|
||||
objs = [Cons 1 2, Cons 2 3, Cons 6 7, Cons 8 9, Cons 10 30]
|
||||
|
||||
df = Table.new [['ord', ord], ['ints', ints], ['reals', reals], ['bools', bools], ['texts', texts], ['objs', objs]]
|
||||
r = df.order_by (Sort_Column_Selector.By_Name [Sort_Column.Name 'ord'])
|
||||
r = df.order_by (Sort_Column_Selector.By_Name ['ord'])
|
||||
|
||||
r.at 'ints' . to_vector . should_equal [1, 5, 3, 2, 4]
|
||||
df.at 'ints' . to_vector . should_equal ints
|
||||
|
Loading…
Reference in New Issue
Block a user