diff --git a/README.md b/README.md index 33be4a7..7c3b5a9 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,7 @@ gcond.Switch[string](3). Processing value `T` Usage: + ```go import ( "github.com/bytedance/gg/gvalue" @@ -338,6 +339,8 @@ Example5:Convert to map ```go ToMap([]int{1, 2, 3, 4, 5}, func(i int) (string, int) { return strconv.Itoa(i), i }) // {"1":1, "2":2, "3":3, "4":4, "5":5} +ToBoolMap([]int{1, 2, 3, 3, 2}) +// {1: true, 2: true, 3: true} ToMapValues([]int{1, 2, 3, 4, 5}, strconv.Itoa) // {"1":1, "2":2, "3":3, "4":4, "5":5} GroupBy([]int{1, 2, 3, 4, 5}, func(i int) string { @@ -385,6 +388,7 @@ Reverse(s4) Processing map `map[K]V` Usage: + ```go import ( "github.com/bytedance/gg/gmap" @@ -596,7 +600,7 @@ import jsoniter "github.com/json-iterator/go" gson.MarshalBy(jsoniter.ConfigDefault, testcase) // []byte(`{"name":"test","age":10}`) nil -gson.MarshalString(jsoniter.ConfigDefault, testcase) +gson.MarshalString(jsoniter.ConfigDefault, testcase) // {"name":"test","age":10}`, nil gson.UnmarshalBy[testStruct](jsoniter.ConfigDefault, `{"name":"test","age":10}`) // testStruct{Name: "test", Age: 10}, nil @@ -660,7 +664,6 @@ pool.Put(a) Example3:`gsync.OnceXXX` wraps `sync.Once` - ```go onceFunc := gsync.OnceFunc(func() { fmt.Println("OnceFunc") }) onceFunc() @@ -693,7 +696,7 @@ Implementation of tuple provides definition of generic n-ary tuples Usage ```go -import ( +import( "github.com/bytedance/gg/collection/tuple" ) ``` diff --git a/README.zh-CN.md b/README.zh-CN.md index 9e44f6d..f9da8f5 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -338,6 +338,8 @@ gslice.Sum([]int{1, 2, 3, 4, 5}) ```go ToMap([]int{1, 2, 3, 4, 5}, func(i int) (string, int) { return strconv.Itoa(i), i }) // {"1":1, "2":2, "3":3, "4":4, "5":5} +ToBoolMap([]int{1, 2, 3, 3, 2}) +// {1: true, 2: true, 3: true} ToMapValues([]int{1, 2, 3, 4, 5}, strconv.Itoa) // {"1":1, "2":2, "3":3, "4":4, "5":5} GroupBy([]int{1, 2, 3, 4, 5}, func(i int) string { @@ -597,7 +599,7 @@ import jsoniter "github.com/json-iterator/go" gson.MarshalBy(jsoniter.ConfigDefault, testcase) // []byte(`{"name":"test","age":10}`) nil -gson.MarshalString(jsoniter.ConfigDefault, testcase) +gson.MarshalString(jsoniter.ConfigDefault, testcase) // {"name":"test","age":10}`, nil gson.UnmarshalBy[testStruct](jsoniter.ConfigDefault, `{"name":"test","age":10}`) // testStruct{Name: "test", Age: 10}, nil diff --git a/gslice/gslice.go b/gslice/gslice.go index d213a89..556ecc1 100644 --- a/gslice/gslice.go +++ b/gslice/gslice.go @@ -54,7 +54,7 @@ // // Convert to Map: // -// - [ToMap], [ToMapValues] +// - [ToMap], [ToMapValues], [ToBoolMap] // - [GroupBy] // // Set operations: @@ -1116,6 +1116,22 @@ func ToMapValues[T any, K comparable](s []T, f func(T) K) map[K]T { return iter.ToMapValues(f, iter.StealSlice(s)) } +// ToBoolMap collects elements of a slice into a set-like structure represented by map[T]bool. +// Each unique element from the input slice becomes a key in the map with the value `true`. +// Duplicate elements are automatically de-duplicated due to map key uniqueness. +// +// 🚀 EXAMPLE: +// +// s := []int{1, 2, 2, 3} +// ToBoolMap(s) ⏩ map[int]bool{1: true, 2: true, 3: true} +// +// 💡 NOTE: +// +// The element type T must be comparable, as required by Go map keys. +func ToBoolMap[T comparable](s []T) map[T]bool { + return ToMap(s, func(t T) (T, bool) { return t, true }) +} + // PtrOf returns pointers that point to equivalent elements of slice s. // ([]T → []*T). // diff --git a/gslice/gslice_example_test.go b/gslice/gslice_example_test.go index 7c5a1c7..42aa940 100644 --- a/gslice/gslice_example_test.go +++ b/gslice/gslice_example_test.go @@ -62,6 +62,7 @@ func Example() { // Convert to Map fmt.Println(gson.ToString(ToMap([]int{1, 2, 3, 4, 5}, func(i int) (string, int) { return strconv.Itoa(i), i }))) // {"1":1,"2":2,"3":3,"4":4,"5":5} fmt.Println(gson.ToString(ToMapValues([]int{1, 2, 3, 4, 5}, strconv.Itoa))) // {"1":1,"2":2,"3":3,"4":4,"5":5} + fmt.Println(gson.ToString(ToBoolMap([]int{1, 2, 3, 3, 2}))) // {"1":true,"2":true,"3":true} fmt.Println(gson.ToString(GroupBy([]int{1, 2, 3, 4, 5}, func(i int) string { if i%2 == 0 { return "even" @@ -119,6 +120,7 @@ func Example() { // 15 // {"1":1,"2":2,"3":3,"4":4,"5":5} // {"1":1,"2":2,"3":3,"4":4,"5":5} + // {"1":true,"2":true,"3":true} // {"even":[2,4],"odd":[1,3,5]} // [1 2 3 4 5] // [3] diff --git a/gslice/gslice_test.go b/gslice/gslice_test.go index d5c9a6d..35d9b08 100644 --- a/gslice/gslice_test.go +++ b/gslice/gslice_test.go @@ -690,6 +690,14 @@ func TestToMap(t *testing.T) { ToMap([]Foo{{1, "one"}, {2, "two"}, {3, "three"}}, mapper)) } +func TestToBoolMap(t *testing.T) { + assert.Equal(t, map[int]bool{}, ToBoolMap([]int{})) + assert.Equal(t, map[int]bool{1: true, 2: true, 3: true}, ToBoolMap([]int{1, 2, 2, 3})) + assert.Equal(t, + map[string]bool{"a": true, "b": true}, + ToBoolMap([]string{"a", "b", "a", "a", "b"})) +} + func TestDivide(t *testing.T) { { s := []int{0, 1, 2, 3, 4}