From 243365feef5055d780fdd59225f4b4c161a63a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Wa=C5=9Bko?= Date: Mon, 29 May 2023 18:51:11 +0200 Subject: [PATCH] Implement grouping. First steps towards #6292 --- .../src/Internal/Add_Row_Number.enso | 22 +++++++++- .../src/Internal/Multi_Value_Key.enso | 41 +++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Multi_Value_Key.enso diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Add_Row_Number.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Add_Row_Number.enso index 8b4679ba252f9..48a75e7f21717 100644 --- a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Add_Row_Number.enso +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Add_Row_Number.enso @@ -5,6 +5,7 @@ import project.Data.Column_Selector.Column_Selector import project.Data.Sort_Column.Sort_Column import project.Data.Set_Mode.Set_Mode import project.Data.Table.Table +import project.Internal.Multi_Value_Key.Multi_Value_Key import project.Internal.Problem_Builder.Problem_Builder import project.Internal.Table_Helpers import project.Internal.Unique_Name_Strategy.Unique_Name_Strategy @@ -23,7 +24,7 @@ add_row_number table name="Row" from=1 step=1 group_by=[] order_by=[] on_problem True -> case grouping_columns.is_empty of True -> make_range_column name from step table.row_count - False -> Error.throw "TODO: not implemented yet" + False -> make_grouped_enumeration name grouping_columns from step False -> Error.throw "TODO: not implemented yet" column_names = table.column_names @@ -38,10 +39,27 @@ add_row_number table name="Row" from=1 step=1 group_by=[] order_by=[] on_problem Table.new new_columns renamed_table.set new_column name set_mode=Set_Mode.Add +## PRIVATE +nth_index start step n = + start + n*step + ## PRIVATE make_range_column name start step length = builder = make_long_builder length 0.up_to length . each ix-> - builder.appendLong (start + ix*step) + builder.appendLong (nth_index start step ix) storage = builder.seal Column.from_storage name storage + +## PRIVATE +make_grouped_enumeration name grouping_columns start step = + n = grouping_columns.at 0 . length + column_builder = make_long_builder n + 0.up_to n . fold Map.empty grouping_counters-> ix-> + key = Multi_Value_Key.from_row grouping_columns ix + enum_index = grouping_counters.get key 0 + column_builder.appendLong (nth_index start step enum_index) + new_counters = grouping_counters.insert key (enum_index + 1) + new_counters + storage = column_builder.seal + Column.from_storage name storage diff --git a/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Multi_Value_Key.enso b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Multi_Value_Key.enso new file mode 100644 index 0000000000000..940e531f9b124 --- /dev/null +++ b/distribution/lib/Standard/Table/0.0.0-dev/src/Internal/Multi_Value_Key.enso @@ -0,0 +1,41 @@ +from Standard.Base import all +import Standard.Base.Data.Array_Proxy.Array_Proxy +import Standard.Base.Errors.Illegal_State.Illegal_State + +## PRIVATE + An Enso implementation mirroring `OrderedMultiValueKey` and + `UnorderedMultiValueKey` from the Java helpers. + + The ordered part is implemented by delegating to comparators of its elements. + + The unordered part is implemented by delegating to the hahses of elements. +type Multi_Value_Key + ## PRIVATE + Key values:Vector + + ## PRIVATE + from_row columns row_index = + arr = Array_Proxy.new columns.length column_ix-> + columns . at column_ix . at row_index + values = Vector.from_polyglot_array arr + Multi_Value_Key.Key values + +## PRIVATE +type Multi_Value_Key_Comparator + ## PRIVATE + compare x y = + n = x.values.length + if n != y.values.length then Panic.throw (Illegal_State.Error "Multi_Value_Key used with different number of values: " + x.to_text + " vs " + y.to_text) else + go ix = + if ix >= n then Ordering.Equal else + vx = x.values . at ix + vy = y.values . at ix + cmp = (Comparable.from vx).compare vx vy + if cmp != Ordering.Equal then cmp else + @Tail_Call go (ix + 1) + go 0 + + ## PRIVATE + hash x = (Comparable.from x.values).hash x.values + +Comparable.from (_:Multi_Value_Key) = Multi_Value_Key_Comparator