github.com/gogf/gf@v1.16.9/container/gset/gset_int_set.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  //
     7  
     8  package gset
     9  
    10  import (
    11  	"bytes"
    12  	"github.com/gogf/gf/internal/json"
    13  	"github.com/gogf/gf/internal/rwmutex"
    14  	"github.com/gogf/gf/util/gconv"
    15  )
    16  
    17  type IntSet struct {
    18  	mu   rwmutex.RWMutex
    19  	data map[int]struct{}
    20  }
    21  
    22  // New create and returns a new set, which contains un-repeated items.
    23  // The parameter <safe> is used to specify whether using set in concurrent-safety,
    24  // which is false in default.
    25  func NewIntSet(safe ...bool) *IntSet {
    26  	return &IntSet{
    27  		mu:   rwmutex.Create(safe...),
    28  		data: make(map[int]struct{}),
    29  	}
    30  }
    31  
    32  // NewIntSetFrom returns a new set from <items>.
    33  func NewIntSetFrom(items []int, safe ...bool) *IntSet {
    34  	m := make(map[int]struct{})
    35  	for _, v := range items {
    36  		m[v] = struct{}{}
    37  	}
    38  	return &IntSet{
    39  		mu:   rwmutex.Create(safe...),
    40  		data: m,
    41  	}
    42  }
    43  
    44  // Iterator iterates the set readonly with given callback function <f>,
    45  // if <f> returns true then continue iterating; or false to stop.
    46  func (set *IntSet) Iterator(f func(v int) bool) {
    47  	set.mu.RLock()
    48  	defer set.mu.RUnlock()
    49  	for k, _ := range set.data {
    50  		if !f(k) {
    51  			break
    52  		}
    53  	}
    54  }
    55  
    56  // Add adds one or multiple items to the set.
    57  func (set *IntSet) Add(item ...int) {
    58  	set.mu.Lock()
    59  	if set.data == nil {
    60  		set.data = make(map[int]struct{})
    61  	}
    62  	for _, v := range item {
    63  		set.data[v] = struct{}{}
    64  	}
    65  	set.mu.Unlock()
    66  }
    67  
    68  // AddIfNotExist checks whether item exists in the set,
    69  // it adds the item to set and returns true if it does not exists in the set,
    70  // or else it does nothing and returns false.
    71  //
    72  // Note that, if <item> is nil, it does nothing and returns false.
    73  func (set *IntSet) AddIfNotExist(item int) bool {
    74  	if !set.Contains(item) {
    75  		set.mu.Lock()
    76  		defer set.mu.Unlock()
    77  		if set.data == nil {
    78  			set.data = make(map[int]struct{})
    79  		}
    80  		if _, ok := set.data[item]; !ok {
    81  			set.data[item] = struct{}{}
    82  			return true
    83  		}
    84  	}
    85  	return false
    86  }
    87  
    88  // AddIfNotExistFunc checks whether item exists in the set,
    89  // it adds the item to set and returns true if it does not exists in the set and
    90  // function <f> returns true, or else it does nothing and returns false.
    91  //
    92  // Note that, the function <f> is executed without writing lock.
    93  func (set *IntSet) AddIfNotExistFunc(item int, f func() bool) bool {
    94  	if !set.Contains(item) {
    95  		if f() {
    96  			set.mu.Lock()
    97  			defer set.mu.Unlock()
    98  			if set.data == nil {
    99  				set.data = make(map[int]struct{})
   100  			}
   101  			if _, ok := set.data[item]; !ok {
   102  				set.data[item] = struct{}{}
   103  				return true
   104  			}
   105  		}
   106  	}
   107  	return false
   108  }
   109  
   110  // AddIfNotExistFunc checks whether item exists in the set,
   111  // it adds the item to set and returns true if it does not exists in the set and
   112  // function <f> returns true, or else it does nothing and returns false.
   113  //
   114  // Note that, the function <f> is executed without writing lock.
   115  func (set *IntSet) AddIfNotExistFuncLock(item int, f func() bool) bool {
   116  	if !set.Contains(item) {
   117  		set.mu.Lock()
   118  		defer set.mu.Unlock()
   119  		if set.data == nil {
   120  			set.data = make(map[int]struct{})
   121  		}
   122  		if f() {
   123  			if _, ok := set.data[item]; !ok {
   124  				set.data[item] = struct{}{}
   125  				return true
   126  			}
   127  		}
   128  	}
   129  	return false
   130  }
   131  
   132  // Contains checks whether the set contains <item>.
   133  func (set *IntSet) Contains(item int) bool {
   134  	var ok bool
   135  	set.mu.RLock()
   136  	if set.data != nil {
   137  		_, ok = set.data[item]
   138  	}
   139  	set.mu.RUnlock()
   140  	return ok
   141  }
   142  
   143  // Remove deletes <item> from set.
   144  func (set *IntSet) Remove(item int) {
   145  	set.mu.Lock()
   146  	if set.data != nil {
   147  		delete(set.data, item)
   148  	}
   149  	set.mu.Unlock()
   150  }
   151  
   152  // Size returns the size of the set.
   153  func (set *IntSet) Size() int {
   154  	set.mu.RLock()
   155  	l := len(set.data)
   156  	set.mu.RUnlock()
   157  	return l
   158  }
   159  
   160  // Clear deletes all items of the set.
   161  func (set *IntSet) Clear() {
   162  	set.mu.Lock()
   163  	set.data = make(map[int]struct{})
   164  	set.mu.Unlock()
   165  }
   166  
   167  // Slice returns the a of items of the set as slice.
   168  func (set *IntSet) Slice() []int {
   169  	set.mu.RLock()
   170  	var (
   171  		i   = 0
   172  		ret = make([]int, len(set.data))
   173  	)
   174  	for k, _ := range set.data {
   175  		ret[i] = k
   176  		i++
   177  	}
   178  	set.mu.RUnlock()
   179  	return ret
   180  }
   181  
   182  // Join joins items with a string <glue>.
   183  func (set *IntSet) Join(glue string) string {
   184  	set.mu.RLock()
   185  	defer set.mu.RUnlock()
   186  	if len(set.data) == 0 {
   187  		return ""
   188  	}
   189  	var (
   190  		l      = len(set.data)
   191  		i      = 0
   192  		buffer = bytes.NewBuffer(nil)
   193  	)
   194  	for k, _ := range set.data {
   195  		buffer.WriteString(gconv.String(k))
   196  		if i != l-1 {
   197  			buffer.WriteString(glue)
   198  		}
   199  		i++
   200  	}
   201  	return buffer.String()
   202  }
   203  
   204  // String returns items as a string, which implements like json.Marshal does.
   205  func (set *IntSet) String() string {
   206  	return "[" + set.Join(",") + "]"
   207  }
   208  
   209  // LockFunc locks writing with callback function <f>.
   210  func (set *IntSet) LockFunc(f func(m map[int]struct{})) {
   211  	set.mu.Lock()
   212  	defer set.mu.Unlock()
   213  	f(set.data)
   214  }
   215  
   216  // RLockFunc locks reading with callback function <f>.
   217  func (set *IntSet) RLockFunc(f func(m map[int]struct{})) {
   218  	set.mu.RLock()
   219  	defer set.mu.RUnlock()
   220  	f(set.data)
   221  }
   222  
   223  // Equal checks whether the two sets equal.
   224  func (set *IntSet) Equal(other *IntSet) bool {
   225  	if set == other {
   226  		return true
   227  	}
   228  	set.mu.RLock()
   229  	defer set.mu.RUnlock()
   230  	other.mu.RLock()
   231  	defer other.mu.RUnlock()
   232  	if len(set.data) != len(other.data) {
   233  		return false
   234  	}
   235  	for key := range set.data {
   236  		if _, ok := other.data[key]; !ok {
   237  			return false
   238  		}
   239  	}
   240  	return true
   241  }
   242  
   243  // IsSubsetOf checks whether the current set is a sub-set of <other>.
   244  func (set *IntSet) IsSubsetOf(other *IntSet) bool {
   245  	if set == other {
   246  		return true
   247  	}
   248  	set.mu.RLock()
   249  	defer set.mu.RUnlock()
   250  	other.mu.RLock()
   251  	defer other.mu.RUnlock()
   252  	for key := range set.data {
   253  		if _, ok := other.data[key]; !ok {
   254  			return false
   255  		}
   256  	}
   257  	return true
   258  }
   259  
   260  // Union returns a new set which is the union of <set> and <other>.
   261  // Which means, all the items in <newSet> are in <set> or in <other>.
   262  func (set *IntSet) Union(others ...*IntSet) (newSet *IntSet) {
   263  	newSet = NewIntSet()
   264  	set.mu.RLock()
   265  	defer set.mu.RUnlock()
   266  	for _, other := range others {
   267  		if set != other {
   268  			other.mu.RLock()
   269  		}
   270  		for k, v := range set.data {
   271  			newSet.data[k] = v
   272  		}
   273  		if set != other {
   274  			for k, v := range other.data {
   275  				newSet.data[k] = v
   276  			}
   277  		}
   278  		if set != other {
   279  			other.mu.RUnlock()
   280  		}
   281  	}
   282  
   283  	return
   284  }
   285  
   286  // Diff returns a new set which is the difference set from <set> to <other>.
   287  // Which means, all the items in <newSet> are in <set> but not in <other>.
   288  func (set *IntSet) Diff(others ...*IntSet) (newSet *IntSet) {
   289  	newSet = NewIntSet()
   290  	set.mu.RLock()
   291  	defer set.mu.RUnlock()
   292  	for _, other := range others {
   293  		if set == other {
   294  			continue
   295  		}
   296  		other.mu.RLock()
   297  		for k, v := range set.data {
   298  			if _, ok := other.data[k]; !ok {
   299  				newSet.data[k] = v
   300  			}
   301  		}
   302  		other.mu.RUnlock()
   303  	}
   304  	return
   305  }
   306  
   307  // Intersect returns a new set which is the intersection from <set> to <other>.
   308  // Which means, all the items in <newSet> are in <set> and also in <other>.
   309  func (set *IntSet) Intersect(others ...*IntSet) (newSet *IntSet) {
   310  	newSet = NewIntSet()
   311  	set.mu.RLock()
   312  	defer set.mu.RUnlock()
   313  	for _, other := range others {
   314  		if set != other {
   315  			other.mu.RLock()
   316  		}
   317  		for k, v := range set.data {
   318  			if _, ok := other.data[k]; ok {
   319  				newSet.data[k] = v
   320  			}
   321  		}
   322  		if set != other {
   323  			other.mu.RUnlock()
   324  		}
   325  	}
   326  	return
   327  }
   328  
   329  // Complement returns a new set which is the complement from <set> to <full>.
   330  // Which means, all the items in <newSet> are in <full> and not in <set>.
   331  //
   332  // It returns the difference between <full> and <set>
   333  // if the given set <full> is not the full set of <set>.
   334  func (set *IntSet) Complement(full *IntSet) (newSet *IntSet) {
   335  	newSet = NewIntSet()
   336  	set.mu.RLock()
   337  	defer set.mu.RUnlock()
   338  	if set != full {
   339  		full.mu.RLock()
   340  		defer full.mu.RUnlock()
   341  	}
   342  	for k, v := range full.data {
   343  		if _, ok := set.data[k]; !ok {
   344  			newSet.data[k] = v
   345  		}
   346  	}
   347  	return
   348  }
   349  
   350  // Merge adds items from <others> sets into <set>.
   351  func (set *IntSet) Merge(others ...*IntSet) *IntSet {
   352  	set.mu.Lock()
   353  	defer set.mu.Unlock()
   354  	for _, other := range others {
   355  		if set != other {
   356  			other.mu.RLock()
   357  		}
   358  		for k, v := range other.data {
   359  			set.data[k] = v
   360  		}
   361  		if set != other {
   362  			other.mu.RUnlock()
   363  		}
   364  	}
   365  	return set
   366  }
   367  
   368  // Sum sums items.
   369  // Note: The items should be converted to int type,
   370  // or you'd get a result that you unexpected.
   371  func (set *IntSet) Sum() (sum int) {
   372  	set.mu.RLock()
   373  	defer set.mu.RUnlock()
   374  	for k, _ := range set.data {
   375  		sum += k
   376  	}
   377  	return
   378  }
   379  
   380  // Pops randomly pops an item from set.
   381  func (set *IntSet) Pop() int {
   382  	set.mu.Lock()
   383  	defer set.mu.Unlock()
   384  	for k, _ := range set.data {
   385  		delete(set.data, k)
   386  		return k
   387  	}
   388  	return 0
   389  }
   390  
   391  // Pops randomly pops <size> items from set.
   392  // It returns all items if size == -1.
   393  func (set *IntSet) Pops(size int) []int {
   394  	set.mu.Lock()
   395  	defer set.mu.Unlock()
   396  	if size > len(set.data) || size == -1 {
   397  		size = len(set.data)
   398  	}
   399  	if size <= 0 {
   400  		return nil
   401  	}
   402  	index := 0
   403  	array := make([]int, size)
   404  	for k, _ := range set.data {
   405  		delete(set.data, k)
   406  		array[index] = k
   407  		index++
   408  		if index == size {
   409  			break
   410  		}
   411  	}
   412  	return array
   413  }
   414  
   415  // Walk applies a user supplied function <f> to every item of set.
   416  func (set *IntSet) Walk(f func(item int) int) *IntSet {
   417  	set.mu.Lock()
   418  	defer set.mu.Unlock()
   419  	m := make(map[int]struct{}, len(set.data))
   420  	for k, v := range set.data {
   421  		m[f(k)] = v
   422  	}
   423  	set.data = m
   424  	return set
   425  }
   426  
   427  // MarshalJSON implements the interface MarshalJSON for json.Marshal.
   428  func (set *IntSet) MarshalJSON() ([]byte, error) {
   429  	return json.Marshal(set.Slice())
   430  }
   431  
   432  // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
   433  func (set *IntSet) UnmarshalJSON(b []byte) error {
   434  	set.mu.Lock()
   435  	defer set.mu.Unlock()
   436  	if set.data == nil {
   437  		set.data = make(map[int]struct{})
   438  	}
   439  	var array []int
   440  	if err := json.UnmarshalUseNumber(b, &array); err != nil {
   441  		return err
   442  	}
   443  	for _, v := range array {
   444  		set.data[v] = struct{}{}
   445  	}
   446  	return nil
   447  }
   448  
   449  // UnmarshalValue is an interface implement which sets any type of value for set.
   450  func (set *IntSet) UnmarshalValue(value interface{}) (err error) {
   451  	set.mu.Lock()
   452  	defer set.mu.Unlock()
   453  	if set.data == nil {
   454  		set.data = make(map[int]struct{})
   455  	}
   456  	var array []int
   457  	switch value.(type) {
   458  	case string, []byte:
   459  		err = json.UnmarshalUseNumber(gconv.Bytes(value), &array)
   460  	default:
   461  		array = gconv.SliceInt(value)
   462  	}
   463  	for _, v := range array {
   464  		set.data[v] = struct{}{}
   465  	}
   466  	return
   467  }