github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/general/sorter.go (about)

     1  /*
     2  Copyright 2022 The Katalyst Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package general
    18  
    19  import (
    20  	"sort"
    21  )
    22  
    23  // CmpFunc compares object-1 and object-2 and returns:
    24  //
    25  //   -1 if object-1 <  object-2
    26  //    0 if object-1 == object-2
    27  //   +1 if object-1 >  object-2
    28  //
    29  
    30  type CmpFunc func(i1, i2 interface{}) int
    31  
    32  type SourceList interface {
    33  	Len() int
    34  	GetSource(index int) interface{}
    35  	SetSource(index int, s interface{})
    36  }
    37  
    38  // MultiSorter implements the Sort interface, sorting changes within.
    39  type MultiSorter struct {
    40  	cmp []CmpFunc
    41  }
    42  
    43  // NewMultiSorter returns a Sorter that sorts using the cmp functions, in order.
    44  // Call its Sort method to sort the data.
    45  func NewMultiSorter(cmp ...CmpFunc) *MultiSorter {
    46  	return &MultiSorter{
    47  		cmp: cmp,
    48  	}
    49  }
    50  
    51  // Sort sorts the argument slice according to the Less functions passed to NewMultiSorter.
    52  func (ms *MultiSorter) Sort(sources SourceList) {
    53  	sort.Sort(&sortableSourceList{
    54  		sources: sources,
    55  		cmp:     ms.cmp,
    56  	})
    57  }
    58  
    59  type sortableSourceList struct {
    60  	sources SourceList
    61  	cmp     []CmpFunc
    62  }
    63  
    64  // Len is part of sort.Interface.
    65  func (ms *sortableSourceList) Len() int {
    66  	return ms.sources.Len()
    67  }
    68  
    69  // Swap is part of sort.Interface.
    70  func (ms *sortableSourceList) Swap(i, j int) {
    71  	si, sj := ms.sources.GetSource(i), ms.sources.GetSource(j)
    72  	ms.sources.SetSource(i, sj)
    73  	ms.sources.SetSource(j, si)
    74  }
    75  
    76  // Less is part of sort.Interface.
    77  func (ms *sortableSourceList) Less(i, j int) bool {
    78  	s1, s2 := ms.sources.GetSource(i), ms.sources.GetSource(j)
    79  	var k int
    80  	for k = 0; k < len(ms.cmp)-1; k++ {
    81  		cmpResult := ms.cmp[k](s1, s2)
    82  		// p1 is less than p2
    83  		if cmpResult < 0 {
    84  			return true
    85  		}
    86  		// p1 is greater than p2
    87  		if cmpResult > 0 {
    88  			return false
    89  		}
    90  		// we don't know yet
    91  	}
    92  	// the last cmp func is the final decider
    93  	return ms.cmp[k](s1, s2) < 0
    94  }
    95  
    96  // CmpBool compares booleans, placing true before false
    97  func CmpBool(a, b bool) int {
    98  	if a == b {
    99  		return 0
   100  	}
   101  	if !b {
   102  		return -1
   103  	}
   104  	return 1
   105  }
   106  
   107  // CmpError compares errors, placing not nil before nil
   108  func CmpError(err1, err2 error) int {
   109  	if err1 != nil && err2 != nil {
   110  		return 0
   111  	}
   112  	if err1 != nil {
   113  		return -1
   114  	}
   115  	return 1
   116  }
   117  
   118  // CmpFloat64 compares float64s, placing greater before smaller
   119  func CmpFloat64(a, b float64) int {
   120  	if a == b {
   121  		return 0
   122  	}
   123  	if a < b {
   124  		return 1
   125  	}
   126  	return -1
   127  }
   128  
   129  // CmpInt32 compares int32s, placing greater before smaller
   130  func CmpInt32(a, b int32) int {
   131  	if a == b {
   132  		return 0
   133  	}
   134  	if a < b {
   135  		return 1
   136  	}
   137  	return -1
   138  }
   139  
   140  // CmpString compares strings, placing greater before smaller
   141  func CmpString(a, b string) int {
   142  	if a == b {
   143  		return 0
   144  	}
   145  
   146  	if a < b {
   147  		return 1
   148  	}
   149  
   150  	return -1
   151  }
   152  
   153  func ReverseCmpFunc(cmpFunc CmpFunc) CmpFunc {
   154  	return func(i1, i2 interface{}) int {
   155  		return -cmpFunc(i1, i2)
   156  	}
   157  }