github.com/zhongdalu/gf@v1.0.0/g/container/gset/gset.go (about)

     1  // Copyright 2017 gf Author(https://github.com/zhongdalu/gf). 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/zhongdalu/gf.
     6  
     7  // Package gset provides kinds of concurrent-safe/unsafe sets.
     8  package gset
     9  
    10  import (
    11  	"github.com/zhongdalu/gf/g/internal/rwmutex"
    12  	"github.com/zhongdalu/gf/g/util/gconv"
    13  	"strings"
    14  )
    15  
    16  type Set struct {
    17  	mu *rwmutex.RWMutex
    18  	m  map[interface{}]struct{}
    19  }
    20  
    21  // New create and returns a new set, which contains un-repeated items.
    22  // The parameter <unsafe> used to specify whether using set in un-concurrent-safety,
    23  // which is false in default.
    24  func New(unsafe ...bool) *Set {
    25  	return NewSet(unsafe...)
    26  }
    27  
    28  // See New.
    29  func NewSet(unsafe ...bool) *Set {
    30  	return &Set{
    31  		m:  make(map[interface{}]struct{}),
    32  		mu: rwmutex.New(unsafe...),
    33  	}
    34  }
    35  
    36  // NewFrom returns a new set from <items>.
    37  // Parameter <items> can be either a variable of any type, or a slice.
    38  func NewFrom(items interface{}, unsafe ...bool) *Set {
    39  	m := make(map[interface{}]struct{})
    40  	for _, v := range gconv.Interfaces(items) {
    41  		m[v] = struct{}{}
    42  	}
    43  	return &Set{
    44  		m:  m,
    45  		mu: rwmutex.New(unsafe...),
    46  	}
    47  }
    48  
    49  // Iterator iterates the set with given callback function <f>,
    50  // if <f> returns true then continue iterating; or false to stop.
    51  func (set *Set) Iterator(f func(v interface{}) bool) *Set {
    52  	set.mu.RLock()
    53  	defer set.mu.RUnlock()
    54  	for k, _ := range set.m {
    55  		if !f(k) {
    56  			break
    57  		}
    58  	}
    59  	return set
    60  }
    61  
    62  // Add adds one or multiple items to the set.
    63  func (set *Set) Add(item ...interface{}) *Set {
    64  	set.mu.Lock()
    65  	for _, v := range item {
    66  		set.m[v] = struct{}{}
    67  	}
    68  	set.mu.Unlock()
    69  	return set
    70  }
    71  
    72  // Contains checks whether the set contains <item>.
    73  func (set *Set) Contains(item interface{}) bool {
    74  	set.mu.RLock()
    75  	_, exists := set.m[item]
    76  	set.mu.RUnlock()
    77  	return exists
    78  }
    79  
    80  // Remove deletes <item> from set.
    81  func (set *Set) Remove(item interface{}) *Set {
    82  	set.mu.Lock()
    83  	delete(set.m, item)
    84  	set.mu.Unlock()
    85  	return set
    86  }
    87  
    88  // Size returns the size of the set.
    89  func (set *Set) Size() int {
    90  	set.mu.RLock()
    91  	l := len(set.m)
    92  	set.mu.RUnlock()
    93  	return l
    94  }
    95  
    96  // Clear deletes all items of the set.
    97  func (set *Set) Clear() *Set {
    98  	set.mu.Lock()
    99  	set.m = make(map[interface{}]struct{})
   100  	set.mu.Unlock()
   101  	return set
   102  }
   103  
   104  // Slice returns the a of items of the set as slice.
   105  func (set *Set) Slice() []interface{} {
   106  	set.mu.RLock()
   107  	i := 0
   108  	ret := make([]interface{}, len(set.m))
   109  	for item := range set.m {
   110  		ret[i] = item
   111  		i++
   112  	}
   113  	set.mu.RUnlock()
   114  	return ret
   115  }
   116  
   117  // Join joins items with a string <glue>.
   118  func (set *Set) Join(glue string) string {
   119  	return strings.Join(gconv.Strings(set.Slice()), ",")
   120  }
   121  
   122  // String returns items as a string, which are joined by char ','.
   123  func (set *Set) String() string {
   124  	return set.Join(",")
   125  }
   126  
   127  // LockFunc locks writing with callback function <f>.
   128  func (set *Set) LockFunc(f func(m map[interface{}]struct{})) {
   129  	set.mu.Lock()
   130  	defer set.mu.Unlock()
   131  	f(set.m)
   132  }
   133  
   134  // RLockFunc locks reading with callback function <f>.
   135  func (set *Set) RLockFunc(f func(m map[interface{}]struct{})) {
   136  	set.mu.RLock()
   137  	defer set.mu.RUnlock()
   138  	f(set.m)
   139  }
   140  
   141  // Equal checks whether the two sets equal.
   142  func (set *Set) Equal(other *Set) bool {
   143  	if set == other {
   144  		return true
   145  	}
   146  	set.mu.RLock()
   147  	defer set.mu.RUnlock()
   148  	other.mu.RLock()
   149  	defer other.mu.RUnlock()
   150  	if len(set.m) != len(other.m) {
   151  		return false
   152  	}
   153  	for key := range set.m {
   154  		if _, ok := other.m[key]; !ok {
   155  			return false
   156  		}
   157  	}
   158  	return true
   159  }
   160  
   161  // IsSubsetOf checks whether the current set is a sub-set of <other>.
   162  func (set *Set) IsSubsetOf(other *Set) bool {
   163  	if set == other {
   164  		return true
   165  	}
   166  	set.mu.RLock()
   167  	defer set.mu.RUnlock()
   168  	other.mu.RLock()
   169  	defer other.mu.RUnlock()
   170  	for key := range set.m {
   171  		if _, ok := other.m[key]; !ok {
   172  			return false
   173  		}
   174  	}
   175  	return true
   176  }
   177  
   178  // Union returns a new set which is the union of <set> and <others>.
   179  // Which means, all the items in <newSet> are in <set> or in <others>.
   180  func (set *Set) Union(others ...*Set) (newSet *Set) {
   181  	newSet = NewSet(true)
   182  	set.mu.RLock()
   183  	defer set.mu.RUnlock()
   184  	for _, other := range others {
   185  		if set != other {
   186  			other.mu.RLock()
   187  		}
   188  		for k, v := range set.m {
   189  			newSet.m[k] = v
   190  		}
   191  		if set != other {
   192  			for k, v := range other.m {
   193  				newSet.m[k] = v
   194  			}
   195  		}
   196  		if set != other {
   197  			other.mu.RUnlock()
   198  		}
   199  	}
   200  
   201  	return
   202  }
   203  
   204  // Diff returns a new set which is the difference set from <set> to <others>.
   205  // Which means, all the items in <newSet> are in <set> but not in <others>.
   206  func (set *Set) Diff(others ...*Set) (newSet *Set) {
   207  	newSet = NewSet(true)
   208  	set.mu.RLock()
   209  	defer set.mu.RUnlock()
   210  	for _, other := range others {
   211  		if set == other {
   212  			continue
   213  		}
   214  		other.mu.RLock()
   215  		for k, v := range set.m {
   216  			if _, ok := other.m[k]; !ok {
   217  				newSet.m[k] = v
   218  			}
   219  		}
   220  		other.mu.RUnlock()
   221  	}
   222  	return
   223  }
   224  
   225  // Intersect returns a new set which is the intersection from <set> to <others>.
   226  // Which means, all the items in <newSet> are in <set> and also in <others>.
   227  func (set *Set) Intersect(others ...*Set) (newSet *Set) {
   228  	newSet = NewSet(true)
   229  	set.mu.RLock()
   230  	defer set.mu.RUnlock()
   231  	for _, other := range others {
   232  		if set != other {
   233  			other.mu.RLock()
   234  		}
   235  		for k, v := range set.m {
   236  			if _, ok := other.m[k]; ok {
   237  				newSet.m[k] = v
   238  			}
   239  		}
   240  		if set != other {
   241  			other.mu.RUnlock()
   242  		}
   243  	}
   244  	return
   245  }
   246  
   247  // Complement returns a new set which is the complement from <set> to <full>.
   248  // Which means, all the items in <newSet> are in <full> and not in <set>.
   249  //
   250  // It returns the difference between <full> and <set>
   251  // if the given set <full> is not the full set of <set>.
   252  func (set *Set) Complement(full *Set) (newSet *Set) {
   253  	newSet = NewSet(true)
   254  	set.mu.RLock()
   255  	defer set.mu.RUnlock()
   256  	if set != full {
   257  		full.mu.RLock()
   258  		defer full.mu.RUnlock()
   259  	}
   260  	for k, v := range full.m {
   261  		if _, ok := set.m[k]; !ok {
   262  			newSet.m[k] = v
   263  		}
   264  	}
   265  	return
   266  }
   267  
   268  // Merge adds items from <others> sets into <set>.
   269  func (set *Set) Merge(others ...*Set) *Set {
   270  	set.mu.Lock()
   271  	defer set.mu.Unlock()
   272  	for _, other := range others {
   273  		if set != other {
   274  			other.mu.RLock()
   275  		}
   276  		for k, v := range other.m {
   277  			set.m[k] = v
   278  		}
   279  		if set != other {
   280  			other.mu.RUnlock()
   281  		}
   282  	}
   283  	return set
   284  }
   285  
   286  // Sum sums items.
   287  // Note: The items should be converted to int type,
   288  // or you'd get a result that you unexpected.
   289  func (set *Set) Sum() (sum int) {
   290  	set.mu.RLock()
   291  	defer set.mu.RUnlock()
   292  	for k, _ := range set.m {
   293  		sum += gconv.Int(k)
   294  	}
   295  	return
   296  }
   297  
   298  // Pops randomly pops an item from set.
   299  func (set *Set) Pop(size int) interface{} {
   300  	set.mu.RLock()
   301  	defer set.mu.RUnlock()
   302  	for k, _ := range set.m {
   303  		return k
   304  	}
   305  	return nil
   306  }
   307  
   308  // Pops randomly pops <size> items from set.
   309  func (set *Set) Pops(size int) []interface{} {
   310  	set.mu.RLock()
   311  	defer set.mu.RUnlock()
   312  	if size > len(set.m) {
   313  		size = len(set.m)
   314  	}
   315  	index := 0
   316  	array := make([]interface{}, size)
   317  	for k, _ := range set.m {
   318  		array[index] = k
   319  		index++
   320  		if index == size {
   321  			break
   322  		}
   323  	}
   324  	return array
   325  }