github.com/haraldrudell/parl@v0.4.176/pslices/insert.go (about)

     1  /*
     2  © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package pslices
     7  
     8  import (
     9  	"github.com/haraldrudell/parl/perrors"
    10  	"golang.org/x/exp/constraints"
    11  	"golang.org/x/exp/slices"
    12  )
    13  
    14  // InsertOrdered inserts value into an ordered slice
    15  //   - duplicate values are allowed, new values are placed at the end
    16  //   - insert is O(log n)
    17  func InsertOrdered[E constraints.Ordered](slice0 []E, value E) (slice []E) {
    18  
    19  	// find position
    20  	var position int
    21  	var wasFound bool
    22  	if position, wasFound = slices.BinarySearch(slice0, value); wasFound {
    23  
    24  		// advance beyond last identical value
    25  		for {
    26  			position++
    27  			if position == len(slice0) || slice0[position] != value {
    28  				break
    29  			}
    30  		}
    31  	}
    32  
    33  	return slices.Insert(slice0, position, value)
    34  }
    35  
    36  // InsertOrderedFunc inserts a value into a slice making it ordered using a comparison function.
    37  //   - duplicate values are allowed, new values are placed at the end
    38  //   - insert is O(log n)
    39  //   - cmp function can be provided by E being a type with Cmp method.
    40  //   - cmp(a, b) is expected to return an integer comparing the two parameters:
    41  //     0 if a == b, a negative number if a < b and a positive number if a > b
    42  func InsertOrderedFunc[E any](slice0 []E, value E, cmp func(a, b E) (result int)) (slice []E) {
    43  
    44  	// obtain comparison function
    45  	if cmp == nil {
    46  		panic(perrors.NewPF("cmp cannot be nil"))
    47  	}
    48  
    49  	// find position
    50  	var position int
    51  	var wasFound bool
    52  	if position, wasFound = slices.BinarySearchFunc(slice0, value, cmp); wasFound {
    53  
    54  		// advance beyond last identical value
    55  		for {
    56  			position++
    57  			if position == len(slice0) || cmp(value, slice0[position]) != 0 {
    58  				break
    59  			}
    60  		}
    61  	}
    62  
    63  	return slices.Insert(slice0, position, value)
    64  }