mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
improve Join/String functions for garray/gset/gmap; add AddIfNotExistFunc/AddIfNotExistFuncLock functions for gset
This commit is contained in:
@ -604,7 +604,7 @@ func (a *Array) CountValues() map[interface{}]int {
|
||||
return m
|
||||
}
|
||||
|
||||
// String returns current array as a string.
|
||||
// String returns current array as a string, which implements like json.Marshal does.
|
||||
func (a *Array) String() string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
@ -619,7 +619,7 @@ func (a *Array) String() string {
|
||||
buffer.WriteString(`"` + gstr.QuoteMeta(s, `"\`) + `"`)
|
||||
}
|
||||
if k != len(a.array)-1 {
|
||||
buffer.WriteString(",")
|
||||
buffer.WriteByte(',')
|
||||
}
|
||||
}
|
||||
buffer.WriteByte(']')
|
||||
|
||||
@ -610,7 +610,7 @@ func (a *IntArray) CountValues() map[int]int {
|
||||
return m
|
||||
}
|
||||
|
||||
// String returns current array as a string.
|
||||
// String returns current array as a string, which implements like json.Marshal does.
|
||||
func (a *IntArray) String() string {
|
||||
return "[" + a.Join(",") + "]"
|
||||
}
|
||||
|
||||
@ -611,7 +611,7 @@ func (a *StrArray) CountValues() map[string]int {
|
||||
return m
|
||||
}
|
||||
|
||||
// String returns current array as a string.
|
||||
// String returns current array as a string, which implements like json.Marshal does.
|
||||
func (a *StrArray) String() string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
@ -620,7 +620,7 @@ func (a *StrArray) String() string {
|
||||
for k, v := range a.array {
|
||||
buffer.WriteString(`"` + gstr.QuoteMeta(v, `"\`) + `"`)
|
||||
if k != len(a.array)-1 {
|
||||
buffer.WriteString(",")
|
||||
buffer.WriteByte(',')
|
||||
}
|
||||
}
|
||||
buffer.WriteByte(']')
|
||||
|
||||
@ -549,7 +549,7 @@ func (a *SortedArray) CountValues() map[interface{}]int {
|
||||
return m
|
||||
}
|
||||
|
||||
// String returns current array as a string.
|
||||
// String returns current array as a string, which implements like json.Marshal does.
|
||||
func (a *SortedArray) String() string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
@ -564,7 +564,7 @@ func (a *SortedArray) String() string {
|
||||
buffer.WriteString(`"` + gstr.QuoteMeta(s, `"\`) + `"`)
|
||||
}
|
||||
if k != len(a.array)-1 {
|
||||
buffer.WriteString(",")
|
||||
buffer.WriteByte(',')
|
||||
}
|
||||
}
|
||||
buffer.WriteByte(']')
|
||||
|
||||
@ -535,7 +535,7 @@ func (a *SortedIntArray) CountValues() map[int]int {
|
||||
return m
|
||||
}
|
||||
|
||||
// String returns current array as a string.
|
||||
// String returns current array as a string, which implements like json.Marshal does.
|
||||
func (a *SortedIntArray) String() string {
|
||||
return "[" + a.Join(",") + "]"
|
||||
}
|
||||
|
||||
@ -536,7 +536,7 @@ func (a *SortedStrArray) CountValues() map[string]int {
|
||||
return m
|
||||
}
|
||||
|
||||
// String returns current array as a string.
|
||||
// String returns current array as a string, which implements like json.Marshal does.
|
||||
func (a *SortedStrArray) String() string {
|
||||
a.mu.RLock()
|
||||
defer a.mu.RUnlock()
|
||||
@ -545,7 +545,7 @@ func (a *SortedStrArray) String() string {
|
||||
for k, v := range a.array {
|
||||
buffer.WriteString(`"` + gstr.QuoteMeta(v, `"\`) + `"`)
|
||||
if k != len(a.array)-1 {
|
||||
buffer.WriteString(",")
|
||||
buffer.WriteByte(',')
|
||||
}
|
||||
}
|
||||
buffer.WriteByte(']')
|
||||
|
||||
@ -71,6 +71,48 @@ func (set *Set) Add(item ...interface{}) *Set {
|
||||
return set
|
||||
}
|
||||
|
||||
// AddIfNotExistFunc adds the returned value of callback function <f> to the set
|
||||
// if <item> does not exit in the set.
|
||||
func (set *Set) AddIfNotExistFunc(item interface{}, f func() interface{}) *Set {
|
||||
if !set.Contains(item) {
|
||||
set.doAddWithLockCheck(item, f())
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// AddIfNotExistFuncLock adds the returned value of callback function <f> to the set
|
||||
// if <item> does not exit in the set.
|
||||
//
|
||||
// Note that the callback function <f> is executed in the mutex.Lock of the set.
|
||||
func (set *Set) AddIfNotExistFuncLock(item interface{}, f func() interface{}) *Set {
|
||||
if !set.Contains(item) {
|
||||
set.doAddWithLockCheck(item, f)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// doAddWithLockCheck checks whether item exists with mutex.Lock,
|
||||
// if not exists, it adds item to the set or else just returns the existing value.
|
||||
//
|
||||
// If <value> is type of <func() interface {}>,
|
||||
// it will be executed with mutex.Lock of the set,
|
||||
// and its return value will be added to the set.
|
||||
//
|
||||
// It returns item successfully added..
|
||||
func (set *Set) doAddWithLockCheck(item interface{}, value interface{}) interface{} {
|
||||
set.mu.Lock()
|
||||
defer set.mu.Unlock()
|
||||
if _, ok := set.data[item]; !ok && value != nil {
|
||||
if f, ok := value.(func() interface{}); ok {
|
||||
item = f()
|
||||
} else {
|
||||
item = value
|
||||
}
|
||||
}
|
||||
set.data[item] = struct{}{}
|
||||
return item
|
||||
}
|
||||
|
||||
// Contains checks whether the set contains <item>.
|
||||
func (set *Set) Contains(item interface{}) bool {
|
||||
set.mu.RLock()
|
||||
@ -121,6 +163,24 @@ func (set *Set) Join(glue string) string {
|
||||
set.mu.RLock()
|
||||
defer set.mu.RUnlock()
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
l := len(set.data)
|
||||
i := 0
|
||||
for k, _ := range set.data {
|
||||
buffer.WriteString(gconv.String(k))
|
||||
if i != l-1 {
|
||||
buffer.WriteString(glue)
|
||||
}
|
||||
i++
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// String returns items as a string, which implements like json.Marshal does.
|
||||
func (set *Set) String() string {
|
||||
set.mu.RLock()
|
||||
defer set.mu.RUnlock()
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
buffer.WriteByte('[')
|
||||
s := ""
|
||||
l := len(set.data)
|
||||
i := 0
|
||||
@ -132,18 +192,14 @@ func (set *Set) Join(glue string) string {
|
||||
buffer.WriteString(`"` + gstr.QuoteMeta(s, `"\`) + `"`)
|
||||
}
|
||||
if i != l-1 {
|
||||
buffer.WriteString(glue)
|
||||
buffer.WriteByte(',')
|
||||
}
|
||||
i++
|
||||
}
|
||||
buffer.WriteByte(']')
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// String returns items as a string, which are joined by char ','.
|
||||
func (set *Set) String() string {
|
||||
return "[" + set.Join(",") + "]"
|
||||
}
|
||||
|
||||
// LockFunc locks writing with callback function <f>.
|
||||
func (set *Set) LockFunc(f func(m map[interface{}]struct{})) {
|
||||
set.mu.Lock()
|
||||
@ -64,6 +64,48 @@ func (set *IntSet) Add(item ...int) *IntSet {
|
||||
return set
|
||||
}
|
||||
|
||||
// AddIfNotExistFunc adds the returned value of callback function <f> to the set
|
||||
// if <item> does not exit in the set.
|
||||
func (set *IntSet) AddIfNotExistFunc(item int, f func() int) *IntSet {
|
||||
if !set.Contains(item) {
|
||||
set.doAddWithLockCheck(item, f())
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// AddIfNotExistFuncLock adds the returned value of callback function <f> to the set
|
||||
// if <item> does not exit in the set.
|
||||
//
|
||||
// Note that the callback function <f> is executed in the mutex.Lock of the set.
|
||||
func (set *IntSet) AddIfNotExistFuncLock(item int, f func() int) *IntSet {
|
||||
if !set.Contains(item) {
|
||||
set.doAddWithLockCheck(item, f)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// doAddWithLockCheck checks whether item exists with mutex.Lock,
|
||||
// if not exists, it adds item to the set or else just returns the existing value.
|
||||
//
|
||||
// If <value> is type of <func() interface {}>,
|
||||
// it will be executed with mutex.Lock of the set,
|
||||
// and its return value will be added to the set.
|
||||
//
|
||||
// It returns item successfully added..
|
||||
func (set *IntSet) doAddWithLockCheck(item int, value interface{}) int {
|
||||
set.mu.Lock()
|
||||
defer set.mu.Unlock()
|
||||
if _, ok := set.data[item]; !ok && value != nil {
|
||||
if f, ok := value.(func() int); ok {
|
||||
item = f()
|
||||
} else {
|
||||
item = value.(int)
|
||||
}
|
||||
}
|
||||
set.data[item] = struct{}{}
|
||||
return item
|
||||
}
|
||||
|
||||
// Contains checks whether the set contains <item>.
|
||||
func (set *IntSet) Contains(item int) bool {
|
||||
set.mu.RLock()
|
||||
@ -126,7 +168,7 @@ func (set *IntSet) Join(glue string) string {
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// String returns items as a string, which are joined by char ','.
|
||||
// String returns items as a string, which implements like json.Marshal does.
|
||||
func (set *IntSet) String() string {
|
||||
return "[" + set.Join(",") + "]"
|
||||
}
|
||||
|
||||
@ -65,6 +65,48 @@ func (set *StrSet) Add(item ...string) *StrSet {
|
||||
return set
|
||||
}
|
||||
|
||||
// AddIfNotExistFunc adds the returned value of callback function <f> to the set
|
||||
// if <item> does not exit in the set.
|
||||
func (set *StrSet) AddIfNotExistFunc(item string, f func() string) *StrSet {
|
||||
if !set.Contains(item) {
|
||||
set.doAddWithLockCheck(item, f())
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// AddIfNotExistFuncLock adds the returned value of callback function <f> to the set
|
||||
// if <item> does not exit in the set.
|
||||
//
|
||||
// Note that the callback function <f> is executed in the mutex.Lock of the set.
|
||||
func (set *StrSet) AddIfNotExistFuncLock(item string, f func() string) *StrSet {
|
||||
if !set.Contains(item) {
|
||||
set.doAddWithLockCheck(item, f)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
// doAddWithLockCheck checks whether item exists with mutex.Lock,
|
||||
// if not exists, it adds item to the set or else just returns the existing value.
|
||||
//
|
||||
// If <value> is type of <func() interface {}>,
|
||||
// it will be executed with mutex.Lock of the set,
|
||||
// and its return value will be added to the set.
|
||||
//
|
||||
// It returns item successfully added..
|
||||
func (set *StrSet) doAddWithLockCheck(item string, value interface{}) string {
|
||||
set.mu.Lock()
|
||||
defer set.mu.Unlock()
|
||||
if _, ok := set.data[item]; !ok && value != nil {
|
||||
if f, ok := value.(func() string); ok {
|
||||
item = f()
|
||||
} else {
|
||||
item = value.(string)
|
||||
}
|
||||
}
|
||||
set.data[item] = struct{}{}
|
||||
return item
|
||||
}
|
||||
|
||||
// Contains checks whether the set contains <item>.
|
||||
func (set *StrSet) Contains(item string) bool {
|
||||
set.mu.RLock()
|
||||
@ -119,11 +161,7 @@ func (set *StrSet) Join(glue string) string {
|
||||
l := len(set.data)
|
||||
i := 0
|
||||
for k, _ := range set.data {
|
||||
if gstr.IsNumeric(k) {
|
||||
buffer.WriteString(k)
|
||||
} else {
|
||||
buffer.WriteString(`"` + gstr.QuoteMeta(k, `"\`) + `"`)
|
||||
}
|
||||
buffer.WriteString(k)
|
||||
if i != l-1 {
|
||||
buffer.WriteString(glue)
|
||||
}
|
||||
@ -132,9 +170,21 @@ func (set *StrSet) Join(glue string) string {
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// String returns items as a string, which are joined by char ','.
|
||||
// String returns items as a string, which implements like json.Marshal does.
|
||||
func (set *StrSet) String() string {
|
||||
return "[" + set.Join(",") + "]"
|
||||
set.mu.RLock()
|
||||
defer set.mu.RUnlock()
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
l := len(set.data)
|
||||
i := 0
|
||||
for k, _ := range set.data {
|
||||
buffer.WriteString(`"` + gstr.QuoteMeta(k, `"\`) + `"`)
|
||||
if i != l-1 {
|
||||
buffer.WriteByte(',')
|
||||
}
|
||||
i++
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// LockFunc locks writing with callback function <f>.
|
||||
|
||||
@ -220,8 +220,8 @@ func TestSet_Join(t *testing.T) {
|
||||
s1 := gset.New(true)
|
||||
s1.Add("a").Add(`"b"`).Add(`\c`)
|
||||
str1 := s1.Join(",")
|
||||
gtest.Assert(strings.Contains(str1, `\"b\"`), true)
|
||||
gtest.Assert(strings.Contains(str1, `\\c`), true)
|
||||
gtest.Assert(strings.Contains(str1, `"b"`), true)
|
||||
gtest.Assert(strings.Contains(str1, `\c`), true)
|
||||
gtest.Assert(strings.Contains(str1, `a`), true)
|
||||
})
|
||||
}
|
||||
@ -305,3 +305,43 @@ func TestSet_Json(t *testing.T) {
|
||||
gtest.Assert(a3.Contains("e"), false)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSet_AddIfNotExistFunc(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s := gset.New(true)
|
||||
s.Add(1)
|
||||
gtest.Assert(s.Contains(1), true)
|
||||
gtest.Assert(s.Contains(2), false)
|
||||
|
||||
s.AddIfNotExistFunc(2, func() interface{} {
|
||||
return 3
|
||||
})
|
||||
gtest.Assert(s.Contains(2), false)
|
||||
gtest.Assert(s.Contains(3), true)
|
||||
|
||||
s.AddIfNotExistFunc(3, func() interface{} {
|
||||
return 4
|
||||
})
|
||||
gtest.Assert(s.Contains(3), true)
|
||||
gtest.Assert(s.Contains(4), false)
|
||||
})
|
||||
|
||||
gtest.Case(t, func() {
|
||||
s := gset.New(true)
|
||||
s.Add(1)
|
||||
gtest.Assert(s.Contains(1), true)
|
||||
gtest.Assert(s.Contains(2), false)
|
||||
|
||||
s.AddIfNotExistFuncLock(2, func() interface{} {
|
||||
return 3
|
||||
})
|
||||
gtest.Assert(s.Contains(2), false)
|
||||
gtest.Assert(s.Contains(3), true)
|
||||
|
||||
s.AddIfNotExistFuncLock(3, func() interface{} {
|
||||
return 4
|
||||
})
|
||||
gtest.Assert(s.Contains(3), true)
|
||||
gtest.Assert(s.Contains(4), false)
|
||||
})
|
||||
}
|
||||
@ -259,3 +259,43 @@ func TestIntSet_Json(t *testing.T) {
|
||||
gtest.Assert(a2.Contains(5), false)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntSet_AddIfNotExistFunc(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s := gset.NewIntSet(true)
|
||||
s.Add(1)
|
||||
gtest.Assert(s.Contains(1), true)
|
||||
gtest.Assert(s.Contains(2), false)
|
||||
|
||||
s.AddIfNotExistFunc(2, func() int {
|
||||
return 3
|
||||
})
|
||||
gtest.Assert(s.Contains(2), false)
|
||||
gtest.Assert(s.Contains(3), true)
|
||||
|
||||
s.AddIfNotExistFunc(3, func() int {
|
||||
return 4
|
||||
})
|
||||
gtest.Assert(s.Contains(3), true)
|
||||
gtest.Assert(s.Contains(4), false)
|
||||
})
|
||||
|
||||
gtest.Case(t, func() {
|
||||
s := gset.NewIntSet(true)
|
||||
s.Add(1)
|
||||
gtest.Assert(s.Contains(1), true)
|
||||
gtest.Assert(s.Contains(2), false)
|
||||
|
||||
s.AddIfNotExistFuncLock(2, func() int {
|
||||
return 3
|
||||
})
|
||||
gtest.Assert(s.Contains(2), false)
|
||||
gtest.Assert(s.Contains(3), true)
|
||||
|
||||
s.AddIfNotExistFuncLock(3, func() int {
|
||||
return 4
|
||||
})
|
||||
gtest.Assert(s.Contains(3), true)
|
||||
gtest.Assert(s.Contains(4), false)
|
||||
})
|
||||
}
|
||||
|
||||
@ -207,8 +207,8 @@ func TestStrSet_Join(t *testing.T) {
|
||||
s1 := gset.NewStrSet()
|
||||
s1.Add("a").Add(`"b"`).Add(`\c`)
|
||||
str1 := s1.Join(",")
|
||||
gtest.Assert(strings.Contains(str1, `\"b\"`), true)
|
||||
gtest.Assert(strings.Contains(str1, `\\c`), true)
|
||||
gtest.Assert(strings.Contains(str1, `"b"`), true)
|
||||
gtest.Assert(strings.Contains(str1, `\c`), true)
|
||||
gtest.Assert(strings.Contains(str1, `a`), true)
|
||||
})
|
||||
}
|
||||
@ -304,3 +304,43 @@ func TestStrSet_Json(t *testing.T) {
|
||||
gtest.Assert(a3.Contains("e"), false)
|
||||
})
|
||||
}
|
||||
|
||||
func TestStrSet_AddIfNotExistFunc(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s := gset.NewStrSet(true)
|
||||
s.Add("1")
|
||||
gtest.Assert(s.Contains("1"), true)
|
||||
gtest.Assert(s.Contains("2"), false)
|
||||
|
||||
s.AddIfNotExistFunc("2", func() string {
|
||||
return "3"
|
||||
})
|
||||
gtest.Assert(s.Contains("2"), false)
|
||||
gtest.Assert(s.Contains("3"), true)
|
||||
|
||||
s.AddIfNotExistFunc("3", func() string {
|
||||
return "4"
|
||||
})
|
||||
gtest.Assert(s.Contains("3"), true)
|
||||
gtest.Assert(s.Contains("4"), false)
|
||||
})
|
||||
|
||||
gtest.Case(t, func() {
|
||||
s := gset.NewStrSet(true)
|
||||
s.Add("1")
|
||||
gtest.Assert(s.Contains("1"), true)
|
||||
gtest.Assert(s.Contains("2"), false)
|
||||
|
||||
s.AddIfNotExistFuncLock("2", func() string {
|
||||
return "3"
|
||||
})
|
||||
gtest.Assert(s.Contains("2"), false)
|
||||
gtest.Assert(s.Contains("3"), true)
|
||||
|
||||
s.AddIfNotExistFuncLock("3", func() string {
|
||||
return "4"
|
||||
})
|
||||
gtest.Assert(s.Contains("3"), true)
|
||||
gtest.Assert(s.Contains("4"), false)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user