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