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