New Table.input function (#11562)

* New Table.input function for GUI allowing auto parsing and type control

* CHANGELOG.

* Missing import.

* Char not Text.

* Fix imports.
This commit is contained in:
James Dunkerley 2024-11-15 10:50:21 +00:00 committed by GitHub
parent 9dc4e9b090
commit 0543cfaec5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 84 additions and 1 deletions

View File

@ -54,12 +54,15 @@
- [Support for dates before 1900 in Excel and signed AWS requests.][11373]
- [Added `Data.read_many` that allows to read a list of files in a single
operation.][11490]
- [Added `Table.input` allowing creation of typed tables from vectors of data,
including auto parsing text columns.][11562]
[11235]: https://github.com/enso-org/enso/pull/11235
[11255]: https://github.com/enso-org/enso/pull/11255
[11371]: https://github.com/enso-org/enso/pull/11371
[11373]: https://github.com/enso-org/enso/pull/11373
[11490]: https://github.com/enso-org/enso/pull/11490
[11562]: https://github.com/enso-org/enso/pull/11562
#### Enso Language & Runtime

View File

@ -192,6 +192,48 @@ type Table
columns = header.map_with_index i-> name-> [name, rows.map (_.at i)]
Table.new columns
## GROUP Standard.Base.Constants
ICON table_edit
Creates a new table from a set of columns parsing the resulting table.
Arguments:
- columns: A set of either Column objects or set of name, data and
optionally type to construct a column from from. If the data is passed
as Vector Text then it will be parsed into the specified type (defaults
to auto detect).
Returns:
- A Table of all of the input data.
! Error Conditions
- If the vector is improperly defined, an error is returned.
- If there are no columns, an error is returned.
- If column names are not distinct, an error is returned.
- If any columns have an inconsistent number of records, an error is returned.
? Unique Names
Column names must be unique. If a column name is repeated, an error is
thrown.
? Consistent Row Count
All columns must have the same number of rows. If a column has a
different number of entries, an error is thrown.
input : Vector (Vector | Column) -> Table
input columns =
throw_bad_column = Error.throw (Illegal_Argument.Error "Each column must be represented as a Vector of column name (Text), data (vector like elements) and optionally a type (Value_Type), or an existing column.")
resolved_columns = columns.map c-> case c of
_ : Column -> c
_ : Vector -> if c.length < 2 || (c.first . is_a Text).not then throw_bad_column else
raw_column = Column.from_vector c.first (c.at 1)
target_type = c.get 2 Auto
if target_type != Auto && (target_type.is_a Value_Type).not then throw_bad_column else
case raw_column.value_type.is_text of
True -> if target_type != Auto && target_type.is_text then raw_column.cast target_type else raw_column.parse target_type
False -> if target_type == Auto then raw_column else raw_column.cast target_type
_ -> throw_bad_column
resolved_columns.if_not_error <| Table.new resolved_columns
## PRIVATE
A table.

View File

@ -7,7 +7,7 @@ import Standard.Base.Errors.Common.Type_Error
import Standard.Base.Errors.Illegal_Argument.Illegal_Argument
import Standard.Base.Runtime.Debug
from Standard.Table import Table, Column, Sort_Column, Aggregate_Column, Blank_Selector, Value_Type
from Standard.Table import Table, Column, Sort_Column, Aggregate_Column, Blank_Selector, Value_Type, Auto
from Standard.Table.Errors import Invalid_Column_Names, Duplicate_Output_Column_Names, No_Input_Columns_Selected, Missing_Input_Columns, No_Such_Column, Invalid_Value_Type, Row_Count_Mismatch
import Standard.Visualization
@ -90,6 +90,44 @@ add_specs suite_builder =
r2.at "foo" . to_vector . should_equal []
r2.at "bar" . to_vector . should_equal []
group_builder.specify "should allow inputting a table without types" <|
r = Table.input [["foo", [1, 2, 3]], ["bar", [False, True, False]]]
r.column_names . should_equal ["foo", "bar"]
r.columns.map .value_type . should_equal [Value_Type.Integer, Value_Type.Boolean]
r_2 = Table.input [["foo", ["1", "2", "3"]], ["bar", ["False", "True", "false"]]]
r_2.column_names . should_equal ["foo", "bar"]
r_2.columns.map .value_type . should_equal [Value_Type.Integer, Value_Type.Boolean]
r_3 = Table.input [["foo", ["1.0", "2.0", "3.0"]], ["bar", [False, True, False]]]
r_3.column_names . should_equal ["foo", "bar"]
r_3.columns.map .value_type . should_equal [Value_Type.Float, Value_Type.Boolean]
r_4 = Table.input [["foo", ["1", "2", "3"]], ["bar", [Date.new 2023 1 4, Nothing, Date.new 2024 10 2]], ["baz", ["1.0", "2.0", "3.0"]]]
r_4.column_names . should_equal ["foo", "bar", "baz"]
r_4.columns.map .value_type . should_equal [Value_Type.Integer, Value_Type.Date, Value_Type.Float]
r_5 = Table.input [["foo", ["2023-01-04", "2024-10-02"]], ["bar", ["1.0", "2.0"]], ["baz", ["12:34:56", "23:45"]]]
r_5.column_names . should_equal ["foo", "bar", "baz"]
r_5.columns.map .value_type . should_equal [Value_Type.Date, Value_Type.Float, Value_Type.Time]
group_builder.specify "should allow inputting a table with types" <|
r = Table.input [["foo", [1, 2, 3], Value_Type.Float], ["bar", [False, True, False]]]
r.column_names . should_equal ["foo", "bar"]
r.columns.map .value_type . should_equal [Value_Type.Float, Value_Type.Boolean]
r_2 = Table.input [["foo", ["1", "2", "3"], Value_Type.Float], ["bar", ["False", "True", "false"], Value_Type.Char]]
r_2.column_names . should_equal ["foo", "bar"]
r_2.columns.map .value_type . should_equal [Value_Type.Float, Value_Type.Char]
r_3 = Table.input [["foo", ["1.0", "2.0", "3.0"], Value_Type.Integer], ["bar", ["False", "True", "False"], Auto]]
r_3.column_names . should_equal ["foo", "bar"]
r_3.columns.map .value_type . should_equal [Value_Type.Integer, Value_Type.Boolean]
r_4 = Table.input [["foo", ["2023-01-04", "2024-10-02"], Value_Type.Date], ["bar", ["1.0", "2.0"], Value_Type.Char], ["baz", ["12:34:56", "23:45"]]]
r_4.column_names . should_equal ["foo", "bar", "baz"]
r_4.columns.map .value_type . should_equal [Value_Type.Date, Value_Type.Char, Value_Type.Time]
group_builder.specify "should allow creating Enso code from a Table" <|
r = Table.new [["foo", [1, 2, 3]], ["bar", [False, True, False]]]
r.pretty . should_equal "Table.new [['foo', [1, 2, 3]], ['bar', [False, True, False]]]"