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