From 8380d2608a378b12fe2da71890f6564bc4761358 Mon Sep 17 00:00:00 2001 From: Naveen Mahalingam Date: Thu, 14 Mar 2024 09:29:31 -0700 Subject: [PATCH] table: Sort should now work on missing/empty cells; fixes #305 --- table/sort.go | 45 ++++++++++++++++++++++++++------------------- table/sort_test.go | 16 ++++++++++++++++ 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/table/sort.go b/table/sort.go index ae55f30..8110806 100644 --- a/table/sort.go +++ b/table/sort.go @@ -93,34 +93,41 @@ func (rs rowsSorter) Swap(i, j int) { func (rs rowsSorter) Less(i, j int) bool { realI, realJ := rs.sortedIndices[i], rs.sortedIndices[j] - for _, col := range rs.sortBy { - rowI, rowJ, colIdx := rs.rows[realI], rs.rows[realJ], col.Number-1 - if colIdx < len(rowI) && colIdx < len(rowJ) { - shouldContinue, returnValue := rs.lessColumns(rowI, rowJ, colIdx, col) - if !shouldContinue { - return returnValue - } + for _, sortBy := range rs.sortBy { + rowI, rowJ, colIdx := rs.rows[realI], rs.rows[realJ], sortBy.Number-1 + // extract the values/cells from the rows for comparison + iVal, jVal := "", "" + if colIdx < len(rowI) { + iVal = rowI[colIdx] + } + if colIdx < len(rowJ) { + jVal = rowJ[colIdx] + } + // compare and choose whether to continue + shouldContinue, returnValue := rs.lessColumns(iVal, jVal, sortBy) + if !shouldContinue { + return returnValue } } return false } -func (rs rowsSorter) lessColumns(rowI rowStr, rowJ rowStr, colIdx int, col SortBy) (bool, bool) { - if rowI[colIdx] == rowJ[colIdx] { +func (rs rowsSorter) lessColumns(iVal string, jVal string, sortBy SortBy) (bool, bool) { + if iVal == jVal { return true, false - } else if col.Mode == Asc { - return false, rowI[colIdx] < rowJ[colIdx] - } else if col.Mode == Dsc { - return false, rowI[colIdx] > rowJ[colIdx] + } else if sortBy.Mode == Asc { + return false, iVal < jVal + } else if sortBy.Mode == Dsc { + return false, iVal > jVal } - iVal, iErr := strconv.ParseFloat(rowI[colIdx], 64) - jVal, jErr := strconv.ParseFloat(rowJ[colIdx], 64) + iNumVal, iErr := strconv.ParseFloat(iVal, 64) + jNumVal, jErr := strconv.ParseFloat(jVal, 64) if iErr == nil && jErr == nil { - if col.Mode == AscNumeric { - return false, iVal < jVal - } else if col.Mode == DscNumeric { - return false, jVal < iVal + if sortBy.Mode == AscNumeric { + return false, iNumVal < jNumVal + } else if sortBy.Mode == DscNumeric { + return false, jNumVal < iNumVal } } return true, false diff --git a/table/sort_test.go b/table/sort_test.go index d63164d..d4cb5fc 100644 --- a/table/sort_test.go +++ b/table/sort_test.go @@ -131,6 +131,22 @@ func TestTable_sortRows_WithoutName(t *testing.T) { assert.Equal(t, []int{0, 1, 2, 3}, table.getSortedRowIndices()) } +func TestTable_sortRows_MissingCells(t *testing.T) { + table := Table{} + table.AppendRows([]Row{ + {1, "Arya", "Stark", 3000, 9}, + {11, "Sansa", "Stark", 3000}, + {20, "Jon", "Snow", 2000, "You know nothing, Jon Snow!"}, + {300, "Tyrion", "Lannister", 5000, 7}, + }) + table.SetStyle(StyleDefault) + table.initForRenderRows() + + // sort by "First Name" + table.SortBy([]SortBy{{Number: 5, Mode: Asc}}) + assert.Equal(t, []int{1, 3, 0, 2}, table.getSortedRowIndices()) +} + func TestTable_sortRows_InvalidMode(t *testing.T) { table := Table{} table.AppendRows([]Row{