mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-06 13:42:28 +08:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ec3a5af87 | ||
|
|
f31dde97b1 | ||
|
|
1718fd1cf1 | ||
|
|
513c0f829c | ||
|
|
c51a806aff | ||
|
|
3c16d50c4b | ||
|
|
21dd6ab8aa | ||
|
|
f5bf5183cc | ||
|
|
f28b5b2f92 | ||
|
|
79867e8a63 | ||
|
|
19939c2b03 | ||
|
|
bf7ffbfa8d | ||
|
|
cbb46f9cb4 | ||
|
|
3ad142d5d7 | ||
|
|
1a436aeb41 | ||
|
|
1af8fe8daf | ||
|
|
ae54c8db6f | ||
|
|
be942ec33e |
19
README.md
19
README.md
@@ -4,7 +4,7 @@
|
||||
<br/>
|
||||
|
||||

|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
@@ -230,6 +230,22 @@ import "github.com/duke-git/lancet/v2/function"
|
||||
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function.md#Watcher)
|
||||
|
||||
|
||||
### Maputil package includes some functions to manipulate map.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/maputil"
|
||||
```
|
||||
|
||||
#### Function list:
|
||||
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#ForEach)
|
||||
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Filter)
|
||||
- [Intersect](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Intersect)
|
||||
- [Keys](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Keys)
|
||||
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Merge)
|
||||
- [Minus](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Minus)
|
||||
- [Values](https://github.com/duke-git/lancet/blob/main/docs/maputil.md#Values)
|
||||
|
||||
|
||||
### Mathutil package implements some functions for math calculation.
|
||||
|
||||
```go
|
||||
@@ -331,6 +347,7 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SortByField)
|
||||
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Some)
|
||||
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice.md#StringSlice)
|
||||
- [SymmetricDifference](https://github.com/duke-git/lancet/blob/main/docs/slice.md#SymmetricDifference)
|
||||
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Unique)
|
||||
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice.md#Union)
|
||||
- [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice.md#UpdateAt)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<br/>
|
||||
|
||||

|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://github.com/duke-git/lancet/releases)
|
||||
[](https://pkg.go.dev/github.com/duke-git/lancet/v2)
|
||||
[](https://goreportcard.com/report/github.com/duke-git/lancet/v2)
|
||||
[](https://github.com/duke-git/lancet/actions/workflows/codecov.yml)
|
||||
@@ -229,6 +229,22 @@ import "github.com/duke-git/lancet/v2/function"
|
||||
- [Delay](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Delay)
|
||||
- [Watcher](https://github.com/duke-git/lancet/blob/main/docs/function_zh-CN.md#Watcher)
|
||||
|
||||
|
||||
### maputil包包括一些操作map的函数.
|
||||
|
||||
```go
|
||||
import "github.com/duke-git/lancet/v2/maputil"
|
||||
```
|
||||
|
||||
#### 函数列表:
|
||||
- [ForEach](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#ForEach)
|
||||
- [Filter](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Filter)
|
||||
- [Intersect](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Intersect)
|
||||
- [Keys](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Keys)
|
||||
- [Merge](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Merge)
|
||||
- [Minus](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Minus)
|
||||
- [Values](https://github.com/duke-git/lancet/blob/main/docs/maputil_zh-CN.md#Values)
|
||||
|
||||
### mathutil包实现了一些数学计算的函数。
|
||||
|
||||
```go
|
||||
@@ -329,6 +345,7 @@ import "github.com/duke-git/lancet/v2/slice"
|
||||
- [SortByField](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SortByField)
|
||||
- [Some](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Some)
|
||||
- [StringSlice](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#StringSlice)
|
||||
- [SymmetricDifference](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#SymmetricDifference)
|
||||
- [Unique](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Unique)
|
||||
- [Union](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#Union)
|
||||
- [UpdateAt](https://github.com/duke-git/lancet/blob/main/docs/slice_zh-CN.md#UpdateAt)
|
||||
|
||||
@@ -103,3 +103,34 @@ func (s Set[T]) Intersection(other Set[T]) Set[T] {
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
// SymmetricDifference creates a new set whose element is in set1 or set2, but not in both sets
|
||||
func (s Set[T]) SymmetricDifference(other Set[T]) Set[T] {
|
||||
set := NewSet[T]()
|
||||
s.Iterate(func(value T) {
|
||||
if !other.Contain(value) {
|
||||
set.Add(value)
|
||||
}
|
||||
})
|
||||
|
||||
other.Iterate(func(value T) {
|
||||
if !s.Contain(value) {
|
||||
set.Add(value)
|
||||
}
|
||||
})
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
// Minus creates an set of whose element in origin set but not in compared set
|
||||
func (s Set[T]) Minus(comparedSet Set[T]) Set[T] {
|
||||
set := NewSet[T]()
|
||||
|
||||
s.Iterate(func(value T) {
|
||||
if !comparedSet.Contain(value) {
|
||||
set.Add(value)
|
||||
}
|
||||
})
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
@@ -127,3 +127,23 @@ func TestSet_Intersection(t *testing.T) {
|
||||
|
||||
assert.Equal(expected, intersectionSet)
|
||||
}
|
||||
|
||||
func TestSet_SymmetricDifference(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_SymmetricDifference")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(2, 3, 4, 5)
|
||||
|
||||
assert.Equal(NewSet(1, 4, 5), set1.SymmetricDifference(set2))
|
||||
}
|
||||
|
||||
func TestSet_Minus(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSet_Minus")
|
||||
|
||||
set1 := NewSet(1, 2, 3)
|
||||
set2 := NewSet(2, 3, 4, 5)
|
||||
set3 := NewSet(2, 3)
|
||||
|
||||
assert.Equal(NewSet(1), set1.Minus(set2))
|
||||
assert.Equal(NewSet(4, 5), set2.Minus(set3))
|
||||
}
|
||||
|
||||
304
docs/maputil.md
Normal file
304
docs/maputil.md
Normal file
@@ -0,0 +1,304 @@
|
||||
# Maputil
|
||||
Package maputil includes some functions to manipulate map.
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Source:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/maputil/maputil.go](https://github.com/duke-git/lancet/blob/main/maputil/maputil.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Example:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Index
|
||||
- [ForEach](#ForEach)
|
||||
- [Filter](#Filter)
|
||||
- [Intersect](#Intersect)
|
||||
- [Keys](#Keys)
|
||||
- [Merge](#Merge)
|
||||
- [Minus](#Minus)
|
||||
- [Values](#Values)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
|
||||
### <span id="ForEach">ForEach</span>
|
||||
<p>Executes iteratee funcation for every key and value pair in map.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V))
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
"d": 4,
|
||||
}
|
||||
|
||||
var sum int
|
||||
|
||||
maputil.ForEach(m, func(_ string, value int) {
|
||||
sum += value
|
||||
})
|
||||
fmt.Println(sum) // 10
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Filter">Filter</span>
|
||||
<p>Iterates over map, return a new map contains all key and value pairs pass the predicate function.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
"d": 4,
|
||||
"e": 5,
|
||||
}
|
||||
isEven := func(_ string, value int) bool {
|
||||
return value%2 == 0
|
||||
}
|
||||
|
||||
maputil.Filter(m, func(_ string, value int) {
|
||||
sum += value
|
||||
})
|
||||
res := maputil.Filter(m, isEven)
|
||||
fmt.Println(res) // map[string]int{"b": 2, "d": 4,}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Intersect">Intersect</span>
|
||||
<p>Iterates over maps, return a new map of key and value pairs in all given maps.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m1 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
}
|
||||
|
||||
m2 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 6,
|
||||
"d": 7,
|
||||
}
|
||||
|
||||
m3 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 9,
|
||||
"e": 9,
|
||||
}
|
||||
|
||||
fmt.Println(maputil.Intersect(m1)) // map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
|
||||
fmt.Println(maputil.Intersect(m1, m2)) // map[string]int{"a": 1, "b": 2}
|
||||
|
||||
fmt.Println(maputil.Intersect(m1, m2, m3)) // map[string]int{"a": 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Keys">Keys</span>
|
||||
<p>Returns a slice of the map's keys.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Keys[K comparable, V any](m map[K]V) []K
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
keys := maputil.Keys(m)
|
||||
sort.Ints(keys)
|
||||
fmt.Println(keys) // []int{1, 2, 3, 4, 5}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Merge">Merge</span>
|
||||
<p>Merge maps, next key will overwrite previous key.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Merge[K comparable, V any](maps ...map[K]V) map[K]V
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m1 := map[int]string{
|
||||
1: "a",
|
||||
2: "b",
|
||||
}
|
||||
m2 := map[int]string{
|
||||
1: "1",
|
||||
3: "2",
|
||||
}
|
||||
fmt.Println(maputil.Merge(m1, m2)) // map[int]string{1:"1", 2:"b", 3:"2",}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Minus">Minus</span>
|
||||
<p>Creates an map of whose key in mapA but not in mapB.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m1 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
}
|
||||
|
||||
m2 := map[string]int{
|
||||
"a": 11,
|
||||
"b": 22,
|
||||
"d": 33,
|
||||
}
|
||||
|
||||
fmt.Println(maputil.Minus(m1, m2)) //map[string]int{"c": 3}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Values">Values</span>
|
||||
<p>Returns a slice of the map's values.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func Values[K comparable, V any](m map[K]V) []V
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
values := maputil.Values(m)
|
||||
sort.Strings(values)
|
||||
|
||||
fmt.Println(values) // []string{"a", "a", "b", "c", "d"}
|
||||
}
|
||||
```
|
||||
304
docs/maputil_zh-CN.md
Normal file
304
docs/maputil_zh-CN.md
Normal file
@@ -0,0 +1,304 @@
|
||||
# Maputil
|
||||
maputil包包括一些操作map的函数。
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 源码:
|
||||
|
||||
- [https://github.com/duke-git/lancet/blob/main/maputil/maputil.go](https://github.com/duke-git/lancet/blob/main/maputil/maputil.go)
|
||||
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 用法:
|
||||
```go
|
||||
import (
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
```
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## 目录:
|
||||
- [ForEach](#ForEach)
|
||||
- [Filter](#Filter)
|
||||
- [Intersect](#Intersect)
|
||||
- [Keys](#Keys)
|
||||
- [Merge](#Merge)
|
||||
- [Minus](#Minus)
|
||||
- [Values](#Values)
|
||||
|
||||
<div STYLE="page-break-after: always;"></div>
|
||||
|
||||
## API文档:
|
||||
|
||||
|
||||
|
||||
### <span id="ForEach">ForEach</span>
|
||||
<p>对map中的每对key和value执行iteratee函数</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V))
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
"d": 4,
|
||||
}
|
||||
|
||||
var sum int
|
||||
|
||||
maputil.ForEach(m, func(_ string, value int) {
|
||||
sum += value
|
||||
})
|
||||
fmt.Println(sum) // 10
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Filter">Filter</span>
|
||||
<p>迭代map中的每对key和value, 返回符合predicate函数的key, value</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
"d": 4,
|
||||
"e": 5,
|
||||
}
|
||||
isEven := func(_ string, value int) bool {
|
||||
return value%2 == 0
|
||||
}
|
||||
|
||||
maputil.Filter(m, func(_ string, value int) {
|
||||
sum += value
|
||||
})
|
||||
res := maputil.Filter(m, isEven)
|
||||
fmt.Println(res) // map[string]int{"b": 2, "d": 4,}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Intersect">Intersect</span>
|
||||
<p>多个map的交集操作</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m1 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
}
|
||||
|
||||
m2 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 6,
|
||||
"d": 7,
|
||||
}
|
||||
|
||||
m3 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 9,
|
||||
"e": 9,
|
||||
}
|
||||
|
||||
fmt.Println(maputil.Intersect(m1)) // map[string]int{"a": 1, "b": 2, "c": 3}
|
||||
|
||||
fmt.Println(maputil.Intersect(m1, m2)) // map[string]int{"a": 1, "b": 2}
|
||||
|
||||
fmt.Println(maputil.Intersect(m1, m2, m3)) // map[string]int{"a": 1}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Keys">Keys</span>
|
||||
<p>返回map中所有key的切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Keys[K comparable, V any](m map[K]V) []K
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
keys := maputil.Keys(m)
|
||||
sort.Ints(keys)
|
||||
fmt.Println(keys) // []int{1, 2, 3, 4, 5}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Merge">Merge</span>
|
||||
<p>合并多个maps, 相同的key会被后来的key覆盖</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Merge[K comparable, V any](maps ...map[K]V) map[K]V
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m1 := map[int]string{
|
||||
1: "a",
|
||||
2: "b",
|
||||
}
|
||||
m2 := map[int]string{
|
||||
1: "1",
|
||||
3: "2",
|
||||
}
|
||||
fmt.Println(maputil.Merge(m1, m2)) // map[int]string{1:"1", 2:"b", 3:"2",}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### <span id="Minus">Minus</span>
|
||||
<p>返回一个map,其中的key存在于mapA,不存在于mapB.</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m1 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
}
|
||||
|
||||
m2 := map[string]int{
|
||||
"a": 11,
|
||||
"b": 22,
|
||||
"d": 33,
|
||||
}
|
||||
|
||||
fmt.Println(maputil.Minus(m1, m2)) //map[string]int{"c": 3}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Values">Values</span>
|
||||
<p>返回map中所有value的切片</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func Values[K comparable, V any](m map[K]V) []V
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/maputil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
m := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
values := maputil.Values(m)
|
||||
sort.Strings(values)
|
||||
|
||||
fmt.Println(values) // []string{"a", "a", "b", "c", "d"}
|
||||
}
|
||||
```
|
||||
@@ -51,6 +51,7 @@ import (
|
||||
- [SortByField](#SortByField)
|
||||
- [Some](#Some)
|
||||
- [StringSlice](#StringSlice)
|
||||
- [SymmetricDifference](#SymmetricDifference)
|
||||
- [Unique](#Unique)
|
||||
- [Union](#Union)
|
||||
- [UpdateAt](#UpdateAt)
|
||||
@@ -909,6 +910,35 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="SymmetricDifference">SymmetricDifference</span>
|
||||
<p>Create a slice whose element is in given slices, but not in both slices.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```go
|
||||
func SymmetricDifference[T any](slices ...[]T) []T
|
||||
```
|
||||
<b>Example:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := []int{1, 2, 3}
|
||||
s2 := []int{1, 2, 4}
|
||||
s3 := []int{1, 2, 3, 5}
|
||||
|
||||
fmt.Println(slice.SymmetricDifference(s1)) //[]int{1, 2, 3}
|
||||
fmt.Println(slice.SymmetricDifference(s1, s2)) //[]int{3, 4}
|
||||
fmt.Println(slice.SymmetricDifference(s1, s2, s3)) //[]int{3, 4, 5}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### <span id="Unique">Unique</span>
|
||||
<p>Remove duplicate elements in slice.</p>
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ import (
|
||||
- [SortByField](#SortByField)
|
||||
- [Some](#Some)
|
||||
- [StringSlice](#StringSlice)
|
||||
- [SymmetricDifference](#SymmetricDifference)
|
||||
- [Unique](#Unique)
|
||||
- [Union](#Union)
|
||||
- [UpdateAt](#UpdateAt)
|
||||
@@ -909,6 +910,34 @@ func main() {
|
||||
|
||||
|
||||
|
||||
### <span id="SymmetricDifference">SymmetricDifference</span>
|
||||
<p>返回一个切片,其中的元素存在于参数切片中,但不同时存储在于参数切片中(交集取反)</p>
|
||||
|
||||
<b>函数签名:</b>
|
||||
|
||||
```go
|
||||
func SymmetricDifference[T any](slices ...[]T) []T
|
||||
```
|
||||
<b>例子:</b>
|
||||
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/duke-git/lancet/v2/slice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s1 := []int{1, 2, 3}
|
||||
s2 := []int{1, 2, 4}
|
||||
s3 := []int{1, 2, 3, 5}
|
||||
|
||||
fmt.Println(slice.SymmetricDifference(s1)) //[]int{1, 2, 3}
|
||||
fmt.Println(slice.SymmetricDifference(s1, s2)) //[]int{3, 4}
|
||||
fmt.Println(slice.SymmetricDifference(s1, s2, s3)) //[]int{3, 4, 5}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### <span id="Unique">Unique</span>
|
||||
<p>删除切片中的重复元素</p>
|
||||
|
||||
|
||||
107
maputil/map.go
Normal file
107
maputil/map.go
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright 2021 dudaodong@gmail.com. All rights reserved.
|
||||
// Use of this source code is governed by MIT license
|
||||
|
||||
// Package maputil includes some functions to manipulate map.
|
||||
package maputil
|
||||
|
||||
import "reflect"
|
||||
|
||||
// Keys returns a slice of the map's keys
|
||||
func Keys[K comparable, V any](m map[K]V) []K {
|
||||
keys := make([]K, 0, len(m))
|
||||
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
// Values returns a slice of the map's values
|
||||
func Values[K comparable, V any](m map[K]V) []V {
|
||||
values := make([]V, 0, len(m))
|
||||
|
||||
for _, v := range m {
|
||||
values = append(values, v)
|
||||
}
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
// Merge maps, next key will overwrite previous key
|
||||
func Merge[K comparable, V any](maps ...map[K]V) map[K]V {
|
||||
res := make(map[K]V, 0)
|
||||
|
||||
for _, m := range maps {
|
||||
for k, v := range m {
|
||||
res[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// ForEach executes iteratee funcation for every key and value pair in map
|
||||
func ForEach[K comparable, V any](m map[K]V, iteratee func(key K, value V)) {
|
||||
for k, v := range m {
|
||||
iteratee(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
// Filter iterates over map, return a new map contains all key and value pairs pass the predicate function
|
||||
func Filter[K comparable, V any](m map[K]V, predicate func(key K, value V) bool) map[K]V {
|
||||
res := make(map[K]V)
|
||||
|
||||
for k, v := range m {
|
||||
if predicate(k, v) {
|
||||
res[k] = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Intersect iterates over maps, return a new map of key and value pairs in all given maps
|
||||
func Intersect[K comparable, V any](maps ...map[K]V) map[K]V {
|
||||
if len(maps) == 0 {
|
||||
return map[K]V{}
|
||||
}
|
||||
if len(maps) == 1 {
|
||||
return maps[0]
|
||||
}
|
||||
|
||||
res := make(map[K]V)
|
||||
|
||||
reducer := func(m1, m2 map[K]V) map[K]V {
|
||||
m := make(map[K]V)
|
||||
for k, v1 := range m1 {
|
||||
if v2, ok := m2[k]; ok && reflect.DeepEqual(v1, v2) {
|
||||
m[k] = v1
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
reduceMaps := make([]map[K]V, 2, 2)
|
||||
res = reducer(maps[0], maps[1])
|
||||
|
||||
for i := 2; i < len(maps); i++ {
|
||||
reduceMaps[0] = res
|
||||
reduceMaps[1] = maps[i]
|
||||
res = reducer(reduceMaps[0], reduceMaps[1])
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
// Minus creates an map of whose key in mapA but not in mapB
|
||||
func Minus[K comparable, V any](mapA, mapB map[K]V) map[K]V {
|
||||
res := make(map[K]V)
|
||||
|
||||
for k, v := range mapA {
|
||||
if _, ok := mapB[k]; !ok {
|
||||
res[k] = v
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
150
maputil/map_test.go
Normal file
150
maputil/map_test.go
Normal file
@@ -0,0 +1,150 @@
|
||||
package maputil
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestKeys(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestKeys")
|
||||
|
||||
m := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
keys := Keys(m)
|
||||
sort.Ints(keys)
|
||||
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, keys)
|
||||
}
|
||||
|
||||
func TestValues(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestValues")
|
||||
|
||||
m := map[int]string{
|
||||
1: "a",
|
||||
2: "a",
|
||||
3: "b",
|
||||
4: "c",
|
||||
5: "d",
|
||||
}
|
||||
|
||||
values := Values(m)
|
||||
sort.Strings(values)
|
||||
|
||||
assert.Equal([]string{"a", "a", "b", "c", "d"}, values)
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMerge")
|
||||
|
||||
m1 := map[int]string{
|
||||
1: "a",
|
||||
2: "b",
|
||||
}
|
||||
m2 := map[int]string{
|
||||
1: "1",
|
||||
3: "2",
|
||||
}
|
||||
|
||||
expected := map[int]string{
|
||||
1: "1",
|
||||
2: "b",
|
||||
3: "2",
|
||||
}
|
||||
acturl := Merge(m1, m2)
|
||||
|
||||
assert.Equal(expected, acturl)
|
||||
}
|
||||
|
||||
func TestForEach(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestForEach")
|
||||
|
||||
m := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
"d": 4,
|
||||
}
|
||||
|
||||
var sum int
|
||||
|
||||
ForEach(m, func(_ string, value int) {
|
||||
sum += value
|
||||
})
|
||||
|
||||
assert.Equal(10, sum)
|
||||
}
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestFilter")
|
||||
|
||||
m := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
"d": 4,
|
||||
"e": 5,
|
||||
}
|
||||
isEven := func(_ string, value int) bool {
|
||||
return value%2 == 0
|
||||
}
|
||||
|
||||
acturl := Filter(m, isEven)
|
||||
|
||||
assert.Equal(map[string]int{
|
||||
"b": 2,
|
||||
"d": 4,
|
||||
}, acturl)
|
||||
}
|
||||
|
||||
func TestIntersect(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestIntersect")
|
||||
|
||||
m1 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
}
|
||||
|
||||
m2 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 6,
|
||||
"d": 7,
|
||||
}
|
||||
|
||||
m3 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 9,
|
||||
"e": 9,
|
||||
}
|
||||
|
||||
assert.Equal(map[string]int{"a": 1, "b": 2, "c": 3}, Intersect(m1))
|
||||
assert.Equal(map[string]int{"a": 1, "b": 2}, Intersect(m1, m2))
|
||||
assert.Equal(map[string]int{"a": 1}, Intersect(m1, m2, m3))
|
||||
}
|
||||
|
||||
func TestMinus(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestMinus")
|
||||
|
||||
m1 := map[string]int{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3,
|
||||
}
|
||||
|
||||
m2 := map[string]int{
|
||||
"a": 11,
|
||||
"b": 22,
|
||||
"d": 33,
|
||||
}
|
||||
|
||||
assert.Equal(map[string]int{"c": 3}, Minus(m1, m2))
|
||||
}
|
||||
@@ -571,7 +571,6 @@ func Union[T any](slices ...[]T) []T {
|
||||
|
||||
// Intersection creates a slice of unique values that included by all slices.
|
||||
func Intersection[T any](slices ...[]T) []T {
|
||||
var res []T
|
||||
if len(slices) == 0 {
|
||||
return []T{}
|
||||
}
|
||||
@@ -579,28 +578,51 @@ func Intersection[T any](slices ...[]T) []T {
|
||||
return Unique(slices[0])
|
||||
}
|
||||
|
||||
//return elements both in slice1 and slice2
|
||||
reduceFunc := func(slice1, slice2 []T) []T {
|
||||
var res []T
|
||||
|
||||
reducer := func(s1, s2 []T) []T {
|
||||
s := make([]T, 0, 0)
|
||||
for _, v := range slice1 {
|
||||
if Contain(slice2, v) {
|
||||
for _, v := range s1 {
|
||||
if Contain(s2, v) {
|
||||
s = append(s, v)
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
res = reduceFunc(slices[0], slices[1])
|
||||
res = reducer(slices[0], slices[1])
|
||||
|
||||
if len(slices) == 2 {
|
||||
return Unique(res)
|
||||
reduceSlice := make([][]T, 2, 2)
|
||||
for i := 2; i < len(slices); i++ {
|
||||
reduceSlice[0] = res
|
||||
reduceSlice[1] = slices[i]
|
||||
res = reducer(reduceSlice[0], reduceSlice[1])
|
||||
}
|
||||
|
||||
tmp := make([][]T, 2, 2)
|
||||
for i := 2; i < len(slices); i++ {
|
||||
tmp[0] = res
|
||||
tmp[1] = slices[i]
|
||||
res = reduceFunc(tmp[0], tmp[1])
|
||||
return Unique(res)
|
||||
}
|
||||
|
||||
// SymmetricDifference oppoiste operation of intersection function
|
||||
func SymmetricDifference[T any](slices ...[]T) []T {
|
||||
if len(slices) == 0 {
|
||||
return []T{}
|
||||
}
|
||||
if len(slices) == 1 {
|
||||
return Unique(slices[0])
|
||||
}
|
||||
|
||||
res := make([]T, 0)
|
||||
|
||||
intersectSlice := Intersection(slices...)
|
||||
|
||||
for i := 0; i < len(slices); i++ {
|
||||
slice := slices[i]
|
||||
for _, v := range slice {
|
||||
if !Contain(intersectSlice, v) {
|
||||
res = append(res, v)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Unique(res)
|
||||
|
||||
@@ -407,7 +407,18 @@ func TestIntersection(t *testing.T) {
|
||||
for i := 0; i < len(res); i++ {
|
||||
assert.Equal(expected[i], res[i])
|
||||
}
|
||||
// assert.IsNil(Intersection())
|
||||
}
|
||||
|
||||
func TestSymmetricDifference(t *testing.T) {
|
||||
assert := internal.NewAssert(t, "TestSymmetricDifference")
|
||||
|
||||
s1 := []int{1, 2, 3}
|
||||
s2 := []int{1, 2, 4}
|
||||
s3 := []int{1, 2, 3, 5}
|
||||
|
||||
assert.Equal([]int{1, 2, 3}, SymmetricDifference(s1))
|
||||
assert.Equal([]int{3, 4}, SymmetricDifference(s1, s2))
|
||||
assert.Equal([]int{3, 4, 5}, SymmetricDifference(s1, s2, s3))
|
||||
}
|
||||
|
||||
func TestReverse(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user