From 41c2f0c9d2b72037edec5a03c275967d147c7102 Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Mon, 27 Mar 2023 21:46:24 +0200 Subject: [PATCH] feat: `sort_rows` of a `Table` --- src/safeds/data/tabular/containers/_table.py | 53 +++++++++++++------ .../containers/_table/test_sort_rows.py | 25 +++++++++ 2 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 tests/safeds/data/tabular/containers/_table/test_sort_rows.py diff --git a/src/safeds/data/tabular/containers/_table.py b/src/safeds/data/tabular/containers/_table.py index 2ff97c833..3f539862e 100644 --- a/src/safeds/data/tabular/containers/_table.py +++ b/src/safeds/data/tabular/containers/_table.py @@ -272,7 +272,7 @@ def get_column(self, column_name: str) -> Column: if self._schema.has_column(column_name): output_column = Column( self._data.iloc[ - :, [self._schema._get_column_index_by_name(column_name)] + :, [self._schema._get_column_index_by_name(column_name)] ].squeeze(), column_name, self._schema.get_type_of_column(column_name), @@ -853,24 +853,24 @@ def slice( def sort_columns( self, - query: Callable[[Column, Column], int] = lambda col1, col2: ( - col1.name > col2.name - ) - - (col1.name < col2.name), + sorter: Callable[[Column, Column], int] = + lambda col1, col2: (col1.name > col2.name) - (col1.name < col2.name), ) -> Table: """ - Sort a table with the given lambda function. - If no function is given the columns will be sorted alphabetically. - This function uses the default python sort algorithm. - The query returns - 0, if both columns are equal. - < 0, if the first column should be ordered after the second column. - > 0, if the first column should be ordered before the second column. + Sort the columns of a `Table` with the given sorter and return a new `Table`. The original table is not + modified. + + The sorter is a function that takes two columns `col1` and `col2` and returns an integer. If `col1` should be + ordered before `col2`, the function should return a negative number. If `col1` should be ordered after `col2`, + the function should return a positive number. If the original order of `col1` and `col2` should be kept, the + function should return 0. + + If no sorter is given, the columns will be sorted alphabetically by their name. Parameters ---------- - query : a lambda function - The lambda function used to sort the columns. + sorter : Callable[[Column, Column], int] + The function used to sort the columns. Returns ------- @@ -878,9 +878,32 @@ def sort_columns( A new table with sorted columns. """ columns = self.to_columns() - columns.sort(key=functools.cmp_to_key(query)) + columns.sort(key=functools.cmp_to_key(sorter)) return Table.from_columns(columns) + def sort_rows(self, sorter: Callable[[Row, Row], int]) -> Table: + """ + Sort the rows of a `Table` with the given sorter and return a new `Table`. The original table is not modified. + + The sorter is a function that takes two rows `row1` and `row2` and returns an integer. If `row1` should be + ordered before `row2`, the function should return a negative number. If `row1` should be ordered after `row2`, + the function should return a positive number. If the original order of `row1` and `row2` should be kept, the + function should return 0. + + Parameters + ---------- + sorter : Callable[[Row, Row], int] + The function used to sort the rows. + + Returns + ------- + new_table : Table + A new table with sorted rows. + """ + rows = self.to_rows() + rows.sort(key=functools.cmp_to_key(sorter)) + return Table.from_rows(rows) + def split(self, percentage_in_first: float) -> typing.Tuple[Table, Table]: """ Split the table into two new tables. diff --git a/tests/safeds/data/tabular/containers/_table/test_sort_rows.py b/tests/safeds/data/tabular/containers/_table/test_sort_rows.py new file mode 100644 index 000000000..32c2e12f8 --- /dev/null +++ b/tests/safeds/data/tabular/containers/_table/test_sort_rows.py @@ -0,0 +1,25 @@ +from typing import Callable + +import pytest + +from safeds.data.tabular.containers import Table, Row, Column + + +@pytest.mark.parametrize( + ("table", "sorter", "expected"), + [ + # Activate when https://github.com/Safe-DS/Stdlib/issues/75 is fixed. + # ( + # Table.from_columns([Column([], "col1")]), + # lambda row1, row2: row1["col1"] - row2["col1"], + # Table.from_columns([Column([], "col1")]) + # ), + ( + Table.from_columns([Column([3, 2, 1], "col1")]), + lambda row1, row2: row1["col1"] - row2["col1"], + Table.from_columns([Column([1, 2, 3], "col1")]) + ), + ] +) +def test_sort_rows(table: Table, sorter: Callable[[Row, Row], int], expected: Table) -> None: + assert table.sort_rows(sorter) == expected