gset_str_set.go 11 KB

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