github.com/haraldrudell/parl@v0.4.176/sets/basic-set.go (about)

     1  /*
     2  © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package sets
     7  
     8  import (
     9  	"github.com/haraldrudell/parl/iters"
    10  	"github.com/haraldrudell/parl/perrors"
    11  	"github.com/haraldrudell/parl/pfmt"
    12  	"github.com/haraldrudell/parl/plog"
    13  )
    14  
    15  // BasicSet elements are basic-type comparable
    16  type BasicSet[E comparable] struct {
    17  	elementMap map[E]struct{}
    18  	elements   []E
    19  }
    20  
    21  var emptyStuct struct{}
    22  
    23  // NewBasicSet returns a set of basic-type comparable elements
    24  func NewBasicSet[E comparable](elements []E) (set Set[E]) {
    25  	var m = make(map[E]struct{}, len(elements))
    26  	for i, e := range elements {
    27  		if _, ok := m[e]; ok {
    28  			panic(perrors.ErrorfPF(
    29  				"duplicate set-element:"+
    30  					" type E: %T duplicate value: ‘%s’"+
    31  					" number of added values: %d",
    32  				e, pfmt.NoRecurseVPrint(e),
    33  				i,
    34  			))
    35  		}
    36  		m[e] = emptyStuct
    37  	}
    38  	return &BasicSet[E]{
    39  		elementMap: m,
    40  		elements:   elements,
    41  	}
    42  }
    43  
    44  // IsValid returns whether value is part of the set
    45  func (s *BasicSet[E]) IsValid(value E) (isValid bool) {
    46  	_, isValid = s.elementMap[value]
    47  	return
    48  }
    49  
    50  // Iterator allows iteration over all set elements
    51  func (s *BasicSet[E]) Iterator() (iterator iters.Iterator[E]) {
    52  	return iters.NewSliceIterator(s.elements)
    53  }
    54  
    55  // StringT returns a string representation for an element of this set.
    56  // If value is not a valid element, a fmt.Printf value is output like ?'%v'
    57  func (s *BasicSet[E]) StringT(value E) (s2 string) {
    58  	// StringT is intended to be the String method of a named type implementing set.
    59  	// if StringT method code would somehow invoke the T.String method again,
    60  	// this will cause infinite recursion and stack overflow panic.
    61  	s2 = pfmt.NoRecurseVPrint(value)
    62  	if _, ok := s.elementMap[value]; ok {
    63  		return
    64  	}
    65  	s2 = "?‘" + s2 + "’"
    66  
    67  	return
    68  }
    69  
    70  // Description returns a more elaborate string representation
    71  // for an element. Description and StringT may return the same value
    72  func (s *BasicSet[E]) Description(value E) (full string) {
    73  
    74  	// type assert to Element with Description method
    75  	var elementDescription ElementDescription
    76  	var ok bool
    77  	if elementDescription, ok = any(&value).(ElementDescription); !ok {
    78  		return // not a full element return
    79  	}
    80  
    81  	full = elementDescription.Description()
    82  
    83  	return
    84  }
    85  
    86  func (s *BasicSet[E]) String() (s2 string) {
    87  	var e E
    88  	s2 = plog.Sprintf("basicSet_%T:%d", e, len(s.elementMap))
    89  	return
    90  }