...

Source file src/github.com/jedib0t/go-pretty/v6/table/sort.go

Documentation: github.com/jedib0t/go-pretty/v6/table

     1  package table
     2  
     3  import (
     4  	"sort"
     5  	"strconv"
     6  )
     7  
     8  // SortBy defines What to sort (Column Name or Number), and How to sort (Mode).
     9  type SortBy struct {
    10  	// Name is the name of the Column as it appears in the first Header row.
    11  	// If a Header is not provided, or the name is not found in the header, this
    12  	// will not work.
    13  	Name string
    14  	// Number is the Column # from left. When specified, it overrides the Name
    15  	// property. If you know the exact Column number, use this instead of Name.
    16  	Number int
    17  
    18  	// Mode tells the Writer how to Sort. Asc/Dsc/etc.
    19  	Mode SortMode
    20  }
    21  
    22  // SortMode defines How to sort.
    23  type SortMode int
    24  
    25  const (
    26  	// Asc sorts the column in Ascending order alphabetically.
    27  	Asc SortMode = iota
    28  	// AscNumeric sorts the column in Ascending order numerically.
    29  	AscNumeric
    30  	// Dsc sorts the column in Descending order alphabetically.
    31  	Dsc
    32  	// DscNumeric sorts the column in Descending order numerically.
    33  	DscNumeric
    34  )
    35  
    36  type rowsSorter struct {
    37  	rows          []rowStr
    38  	sortBy        []SortBy
    39  	sortedIndices []int
    40  }
    41  
    42  // getSortedRowIndices sorts and returns the row indices in Sorted order as
    43  // directed by Table.sortBy which can be set using Table.SortBy(...)
    44  func (t *Table) getSortedRowIndices() []int {
    45  	sortedIndices := make([]int, len(t.rows))
    46  	for idx := range t.rows {
    47  		sortedIndices[idx] = idx
    48  	}
    49  
    50  	if t.sortBy != nil && len(t.sortBy) > 0 {
    51  		sort.Sort(rowsSorter{
    52  			rows:          t.rows,
    53  			sortBy:        t.parseSortBy(t.sortBy),
    54  			sortedIndices: sortedIndices,
    55  		})
    56  	}
    57  
    58  	return sortedIndices
    59  }
    60  
    61  func (t *Table) parseSortBy(sortBy []SortBy) []SortBy {
    62  	var resSortBy []SortBy
    63  	for _, col := range sortBy {
    64  		colNum := 0
    65  		if col.Number > 0 && col.Number <= t.numColumns {
    66  			colNum = col.Number
    67  		} else if col.Name != "" && len(t.rowsHeader) > 0 {
    68  			for idx, colName := range t.rowsHeader[0] {
    69  				if col.Name == colName {
    70  					colNum = idx + 1
    71  					break
    72  				}
    73  			}
    74  		}
    75  		if colNum > 0 {
    76  			resSortBy = append(resSortBy, SortBy{
    77  				Name:   col.Name,
    78  				Number: colNum,
    79  				Mode:   col.Mode,
    80  			})
    81  		}
    82  	}
    83  	return resSortBy
    84  }
    85  
    86  func (rs rowsSorter) Len() int {
    87  	return len(rs.rows)
    88  }
    89  
    90  func (rs rowsSorter) Swap(i, j int) {
    91  	rs.sortedIndices[i], rs.sortedIndices[j] = rs.sortedIndices[j], rs.sortedIndices[i]
    92  }
    93  
    94  func (rs rowsSorter) Less(i, j int) bool {
    95  	realI, realJ := rs.sortedIndices[i], rs.sortedIndices[j]
    96  	for _, col := range rs.sortBy {
    97  		rowI, rowJ, colIdx := rs.rows[realI], rs.rows[realJ], col.Number-1
    98  		if colIdx < len(rowI) && colIdx < len(rowJ) {
    99  			shouldContinue, returnValue := rs.lessColumns(rowI, rowJ, colIdx, col)
   100  			if !shouldContinue {
   101  				return returnValue
   102  			}
   103  		}
   104  	}
   105  	return false
   106  }
   107  
   108  func (rs rowsSorter) lessColumns(rowI rowStr, rowJ rowStr, colIdx int, col SortBy) (bool, bool) {
   109  	if rowI[colIdx] == rowJ[colIdx] {
   110  		return true, false
   111  	} else if col.Mode == Asc {
   112  		return false, rowI[colIdx] < rowJ[colIdx]
   113  	} else if col.Mode == Dsc {
   114  		return false, rowI[colIdx] > rowJ[colIdx]
   115  	}
   116  
   117  	iVal, iErr := strconv.ParseFloat(rowI[colIdx], 64)
   118  	jVal, jErr := strconv.ParseFloat(rowJ[colIdx], 64)
   119  	if iErr == nil && jErr == nil {
   120  		if col.Mode == AscNumeric {
   121  			return false, iVal < jVal
   122  		} else if col.Mode == DscNumeric {
   123  			return false, jVal < iVal
   124  		}
   125  	}
   126  	return true, false
   127  }
   128  

View as plain text