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