github.com/koko1123/flow-go-1@v0.29.6/model/flow/identifierList.go (about)

     1  package flow
     2  
     3  import (
     4  	"bytes"
     5  	"math/rand"
     6  	"sort"
     7  
     8  	"github.com/rs/zerolog/log"
     9  )
    10  
    11  // IdentifierList defines a sortable list of identifiers
    12  type IdentifierList []Identifier
    13  
    14  // Len returns length of the IdentiferList in the number of stored identifiers.
    15  // It satisfies the sort.Interface making the IdentifierList sortable.
    16  func (il IdentifierList) Len() int {
    17  	return len(il)
    18  }
    19  
    20  // Lookup converts the Identifiers to a lookup table.
    21  func (il IdentifierList) Lookup() map[Identifier]struct{} {
    22  	lookup := make(map[Identifier]struct{}, len(il))
    23  	for _, id := range il {
    24  		lookup[id] = struct{}{}
    25  	}
    26  	return lookup
    27  }
    28  
    29  // Less returns true if element i in the IdentifierList is less than j based on its identifier.
    30  // Otherwise it returns true.
    31  // It satisfies the sort.Interface making the IdentifierList sortable.
    32  func (il IdentifierList) Less(i, j int) bool {
    33  	// bytes package already implements Comparable for []byte.
    34  	switch bytes.Compare(il[i][:], il[j][:]) {
    35  	case -1:
    36  		return true
    37  	case 0, 1:
    38  		return false
    39  	default:
    40  		log.Error().Msg("not fail-able with `bytes.Comparable` bounded [-1, 1].")
    41  		return false
    42  	}
    43  }
    44  
    45  // Swap swaps the element i and j in the IdentifierList.
    46  // It satisfies the sort.Interface making the IdentifierList sortable.
    47  func (il IdentifierList) Swap(i, j int) {
    48  	il[j], il[i] = il[i], il[j]
    49  }
    50  
    51  func (il IdentifierList) Strings() []string {
    52  	var list []string
    53  	for _, id := range il {
    54  		list = append(list, id.String())
    55  	}
    56  
    57  	return list
    58  }
    59  
    60  func (il IdentifierList) Copy() IdentifierList {
    61  	cpy := make(IdentifierList, 0, il.Len())
    62  	return append(cpy, il...)
    63  }
    64  
    65  // Contains returns whether this identifier list contains the target identifier.
    66  func (il IdentifierList) Contains(target Identifier) bool {
    67  	for _, id := range il {
    68  		if target == id {
    69  			return true
    70  		}
    71  	}
    72  	return false
    73  }
    74  
    75  // Union returns a new identifier list containing the union of `il` and `other`.
    76  // There are no duplicates in the output.
    77  func (il IdentifierList) Union(other IdentifierList) IdentifierList {
    78  	// stores the output, the union of the two lists
    79  	union := make(IdentifierList, 0, len(il)+len(other))
    80  	// efficient lookup to avoid duplicates
    81  	lookup := make(map[Identifier]struct{})
    82  
    83  	// add all identifiers, omitted duplicates
    84  	for _, identifier := range append(il.Copy(), other...) {
    85  		if _, exists := lookup[identifier]; exists {
    86  			continue
    87  		}
    88  		union = append(union, identifier)
    89  		lookup[identifier] = struct{}{}
    90  	}
    91  
    92  	return union
    93  }
    94  
    95  // DeterministicSample returns deterministic random sample from the `IdentifierList` using the given seed
    96  func (il IdentifierList) DeterministicSample(size uint, seed int64) IdentifierList {
    97  	rand.Seed(seed)
    98  	return il.Sample(size)
    99  }
   100  
   101  // Sample returns random sample of length 'size' of the ids
   102  // [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
   103  func (il IdentifierList) Sample(size uint) IdentifierList {
   104  	return Sample(size, il...)
   105  }
   106  
   107  // Filter will apply a filter to the identifier list.
   108  func (il IdentifierList) Filter(filter IdentifierFilter) IdentifierList {
   109  	var dup IdentifierList
   110  IDLoop:
   111  	for _, identifier := range il {
   112  		if !filter(identifier) {
   113  			continue IDLoop
   114  		}
   115  		dup = append(dup, identifier)
   116  	}
   117  	return dup
   118  }
   119  
   120  func (il IdentifierList) Sort(less IdentifierOrder) IdentifierList {
   121  	dup := il.Copy()
   122  	sort.Slice(dup, func(i int, j int) bool {
   123  		return less(dup[i], dup[j])
   124  	})
   125  	return dup
   126  }
   127  
   128  // Sorted returns whether the list is sorted by the input ordering.
   129  func (il IdentifierList) Sorted(less IdentifierOrder) bool {
   130  	for i := 0; i < len(il)-1; i++ {
   131  		a := il[i]
   132  		b := il[i+1]
   133  		if !less(a, b) {
   134  			return false
   135  		}
   136  	}
   137  	return true
   138  }