github.com/gogf/gf/v2@v2.7.4/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  
    13  	"github.com/gogf/gf/v2/internal/json"
    14  	"github.com/gogf/gf/v2/internal/rwmutex"
    15  	"github.com/gogf/gf/v2/util/gconv"
    16  )
    17  
    18  // IntSet is consisted of int items.
    19  type IntSet struct {
    20  	mu   rwmutex.RWMutex
    21  	data map[int]struct{}
    22  }
    23  
    24  // NewIntSet create and returns a new set, which contains un-repeated items.
    25  // The parameter `safe` is used to specify whether using set in concurrent-safety,
    26  // which is false in default.
    27  func NewIntSet(safe ...bool) *IntSet {
    28  	return &IntSet{
    29  		mu:   rwmutex.Create(safe...),
    30  		data: make(map[int]struct{}),
    31  	}
    32  }
    33  
    34  // NewIntSetFrom returns a new set from `items`.
    35  func NewIntSetFrom(items []int, safe ...bool) *IntSet {
    36  	m := make(map[int]struct{})
    37  	for _, v := range items {
    38  		m[v] = struct{}{}
    39  	}
    40  	return &IntSet{
    41  		mu:   rwmutex.Create(safe...),
    42  		data: m,
    43  	}
    44  }
    45  
    46  // Iterator iterates the set readonly with given callback function `f`,
    47  // if `f` returns true then continue iterating; or false to stop.
    48  func (set *IntSet) Iterator(f func(v int) bool) {
    49  	for _, k := range set.Slice() {
    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  // AddIfNotExistFuncLock 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 an 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  	if set == nil {
   207  		return ""
   208  	}
   209  	return "[" + set.Join(",") + "]"
   210  }
   211  
   212  // LockFunc locks writing with callback function `f`.
   213  func (set *IntSet) LockFunc(f func(m map[int]struct{})) {
   214  	set.mu.Lock()
   215  	defer set.mu.Unlock()
   216  	f(set.data)
   217  }
   218  
   219  // RLockFunc locks reading with callback function `f`.
   220  func (set *IntSet) RLockFunc(f func(m map[int]struct{})) {
   221  	set.mu.RLock()
   222  	defer set.mu.RUnlock()
   223  	f(set.data)
   224  }
   225  
   226  // Equal checks whether the two sets equal.
   227  func (set *IntSet) Equal(other *IntSet) bool {
   228  	if set == other {
   229  		return true
   230  	}
   231  	set.mu.RLock()
   232  	defer set.mu.RUnlock()
   233  	other.mu.RLock()
   234  	defer other.mu.RUnlock()
   235  	if len(set.data) != len(other.data) {
   236  		return false
   237  	}
   238  	for key := range set.data {
   239  		if _, ok := other.data[key]; !ok {
   240  			return false
   241  		}
   242  	}
   243  	return true
   244  }
   245  
   246  // IsSubsetOf checks whether the current set is a sub-set of `other`.
   247  func (set *IntSet) IsSubsetOf(other *IntSet) bool {
   248  	if set == other {
   249  		return true
   250  	}
   251  	set.mu.RLock()
   252  	defer set.mu.RUnlock()
   253  	other.mu.RLock()
   254  	defer other.mu.RUnlock()
   255  	for key := range set.data {
   256  		if _, ok := other.data[key]; !ok {
   257  			return false
   258  		}
   259  	}
   260  	return true
   261  }
   262  
   263  // Union returns a new set which is the union of `set` and `other`.
   264  // Which means, all the items in `newSet` are in `set` or in `other`.
   265  func (set *IntSet) Union(others ...*IntSet) (newSet *IntSet) {
   266  	newSet = NewIntSet()
   267  	set.mu.RLock()
   268  	defer set.mu.RUnlock()
   269  	for _, other := range others {
   270  		if set != other {
   271  			other.mu.RLock()
   272  		}
   273  		for k, v := range set.data {
   274  			newSet.data[k] = v
   275  		}
   276  		if set != other {
   277  			for k, v := range other.data {
   278  				newSet.data[k] = v
   279  			}
   280  		}
   281  		if set != other {
   282  			other.mu.RUnlock()
   283  		}
   284  	}
   285  
   286  	return
   287  }
   288  
   289  // Diff returns a new set which is the difference set from `set` to `other`.
   290  // Which means, all the items in `newSet` are in `set` but not in `other`.
   291  func (set *IntSet) Diff(others ...*IntSet) (newSet *IntSet) {
   292  	newSet = NewIntSet()
   293  	set.mu.RLock()
   294  	defer set.mu.RUnlock()
   295  	for _, other := range others {
   296  		if set == other {
   297  			continue
   298  		}
   299  		other.mu.RLock()
   300  		for k, v := range set.data {
   301  			if _, ok := other.data[k]; !ok {
   302  				newSet.data[k] = v
   303  			}
   304  		}
   305  		other.mu.RUnlock()
   306  	}
   307  	return
   308  }
   309  
   310  // Intersect returns a new set which is the intersection from `set` to `other`.
   311  // Which means, all the items in `newSet` are in `set` and also in `other`.
   312  func (set *IntSet) Intersect(others ...*IntSet) (newSet *IntSet) {
   313  	newSet = NewIntSet()
   314  	set.mu.RLock()
   315  	defer set.mu.RUnlock()
   316  	for _, other := range others {
   317  		if set != other {
   318  			other.mu.RLock()
   319  		}
   320  		for k, v := range set.data {
   321  			if _, ok := other.data[k]; ok {
   322  				newSet.data[k] = v
   323  			}
   324  		}
   325  		if set != other {
   326  			other.mu.RUnlock()
   327  		}
   328  	}
   329  	return
   330  }
   331  
   332  // Complement returns a new set which is the complement from `set` to `full`.
   333  // Which means, all the items in `newSet` are in `full` and not in `set`.
   334  //
   335  // It returns the difference between `full` and `set`
   336  // if the given set `full` is not the full set of `set`.
   337  func (set *IntSet) Complement(full *IntSet) (newSet *IntSet) {
   338  	newSet = NewIntSet()
   339  	set.mu.RLock()
   340  	defer set.mu.RUnlock()
   341  	if set != full {
   342  		full.mu.RLock()
   343  		defer full.mu.RUnlock()
   344  	}
   345  	for k, v := range full.data {
   346  		if _, ok := set.data[k]; !ok {
   347  			newSet.data[k] = v
   348  		}
   349  	}
   350  	return
   351  }
   352  
   353  // Merge adds items from `others` sets into `set`.
   354  func (set *IntSet) Merge(others ...*IntSet) *IntSet {
   355  	set.mu.Lock()
   356  	defer set.mu.Unlock()
   357  	for _, other := range others {
   358  		if set != other {
   359  			other.mu.RLock()
   360  		}
   361  		for k, v := range other.data {
   362  			set.data[k] = v
   363  		}
   364  		if set != other {
   365  			other.mu.RUnlock()
   366  		}
   367  	}
   368  	return set
   369  }
   370  
   371  // Sum sums items.
   372  // Note: The items should be converted to int type,
   373  // or you'd get a result that you unexpected.
   374  func (set *IntSet) Sum() (sum int) {
   375  	set.mu.RLock()
   376  	defer set.mu.RUnlock()
   377  	for k := range set.data {
   378  		sum += k
   379  	}
   380  	return
   381  }
   382  
   383  // Pop randomly pops an item from set.
   384  func (set *IntSet) Pop() int {
   385  	set.mu.Lock()
   386  	defer set.mu.Unlock()
   387  	for k := range set.data {
   388  		delete(set.data, k)
   389  		return k
   390  	}
   391  	return 0
   392  }
   393  
   394  // Pops randomly pops `size` items from set.
   395  // It returns all items if size == -1.
   396  func (set *IntSet) Pops(size int) []int {
   397  	set.mu.Lock()
   398  	defer set.mu.Unlock()
   399  	if size > len(set.data) || size == -1 {
   400  		size = len(set.data)
   401  	}
   402  	if size <= 0 {
   403  		return nil
   404  	}
   405  	index := 0
   406  	array := make([]int, size)
   407  	for k := range set.data {
   408  		delete(set.data, k)
   409  		array[index] = k
   410  		index++
   411  		if index == size {
   412  			break
   413  		}
   414  	}
   415  	return array
   416  }
   417  
   418  // Walk applies a user supplied function `f` to every item of set.
   419  func (set *IntSet) Walk(f func(item int) int) *IntSet {
   420  	set.mu.Lock()
   421  	defer set.mu.Unlock()
   422  	m := make(map[int]struct{}, len(set.data))
   423  	for k, v := range set.data {
   424  		m[f(k)] = v
   425  	}
   426  	set.data = m
   427  	return set
   428  }
   429  
   430  // MarshalJSON implements the interface MarshalJSON for json.Marshal.
   431  func (set IntSet) MarshalJSON() ([]byte, error) {
   432  	return json.Marshal(set.Slice())
   433  }
   434  
   435  // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
   436  func (set *IntSet) UnmarshalJSON(b []byte) error {
   437  	set.mu.Lock()
   438  	defer set.mu.Unlock()
   439  	if set.data == nil {
   440  		set.data = make(map[int]struct{})
   441  	}
   442  	var array []int
   443  	if err := json.UnmarshalUseNumber(b, &array); err != nil {
   444  		return err
   445  	}
   446  	for _, v := range array {
   447  		set.data[v] = struct{}{}
   448  	}
   449  	return nil
   450  }
   451  
   452  // UnmarshalValue is an interface implement which sets any type of value for set.
   453  func (set *IntSet) UnmarshalValue(value interface{}) (err error) {
   454  	set.mu.Lock()
   455  	defer set.mu.Unlock()
   456  	if set.data == nil {
   457  		set.data = make(map[int]struct{})
   458  	}
   459  	var array []int
   460  	switch value.(type) {
   461  	case string, []byte:
   462  		err = json.UnmarshalUseNumber(gconv.Bytes(value), &array)
   463  	default:
   464  		array = gconv.SliceInt(value)
   465  	}
   466  	for _, v := range array {
   467  		set.data[v] = struct{}{}
   468  	}
   469  	return
   470  }
   471  
   472  // DeepCopy implements interface for deep copy of current type.
   473  func (set *IntSet) DeepCopy() interface{} {
   474  	if set == nil {
   475  		return nil
   476  	}
   477  	set.mu.RLock()
   478  	defer set.mu.RUnlock()
   479  	var (
   480  		slice = make([]int, len(set.data))
   481  		index = 0
   482  	)
   483  	for k := range set.data {
   484  		slice[index] = k
   485  		index++
   486  	}
   487  	return NewIntSetFrom(slice, set.mu.IsSafe())
   488  }