Go语言中切片(slice)和字典(map)扩展方法

Golang
113
0
0
2024-07-27

前言

Go本身slice的方法是较少的,其他语言中的过滤和转换相关的经常使用的方法也没有,我们可以扩展一下方便使用。

切片slice

过滤

方法

通过一个函数参数来过滤所需的元素,只有满足条件元素才返回到结果集中:

func SliceFilter[T any](s []T, fn func(T) bool) []T {
    result := make([]T, 0, len(s))
    for _, v := range s {
        if fn(v) {
            result = append(result, v)
        }
    }

    return result
}

判空也是常用的功能,获取所有非空集:

func SliceFilterNonNil[T any](s []*T) []*T {
    return SliceFilter(s, func(t *T) bool {
        return t != nil
    })
}

调用

package test

import (
	"fmt"
	"strings"
	"testing"
	"xh-control-ws/utils"
)

// 普通的测试
func Test02(t *testing.T) {
	var nameList []string
	nameList = append(nameList, "张三", "李四", "王五")
	result := utils.SliceFilter(nameList, func(item string) bool {
		return strings.HasPrefix(item, "张")
	})
	fmt.Println(result) // 输出过滤后的结果
}

转换

方法

通过一个转换函数,可方便地把原切片转换为新的切片:

func SliceTrans[S, R any](s []S, fn func(S) R) []R {
    result := make([]R, 0, len(s))
    for _, v := range s {
        result = append(result, fn(v))
    }
    return result
}

若只需要转换满足条件的元素,可先过滤再转换:

func SliceTransWithFilter[S, R any](s []S, fn func(S) (R, bool)) []R {
    result := make([]R, 0, len(s))
    for _, v := range s {
        if r, ok := fn(v); ok {
            result = append(result, r)
        }

    }
    return result
}

调用

package test

import (
	"fmt"
	"testing"
	"xh-control-ws/utils"
)

// 普通的测试
func Test02(t *testing.T) {
	var nameList []string
	nameList = append(nameList, "张三", "李四", "王五")
	result := utils.SliceTrans(nameList, func(item string) string {
		return item + "同学"
	})
	fmt.Println(result)
}

累计

对切片中的元素累计,获取一个最终结果:

func SliceAccum[S, R any](init R, s []S, fn func(last R, ele S) R) R {
    result := init
    for _, v := range s {
        result = fn(result, v)
    }

    return result
}

字典 map

过滤

方法

func MapFilter[K comparable, V any](m map[K]V, fn func(key K, value V) bool) map[K]V {
    result := make(map[K]V, len(m))
    for k, v := range m {
        if fn(k, v) {
            result[k] = v
        }
    }

    return result
}

调用

package test

import (
	"fmt"
	"testing"
	"xh-control-ws/utils"
)

// 普通的测试
func Test01(t *testing.T) {
	userinfo := map[string]string{"name": "xiaoming"}
	userinfo["name"] = "xiaohong"
	userinfo["age"] = "18"

	result := utils.MapFilter(userinfo, func(key string, value string) bool {
		return key == "name"
	})
	fmt.Println(result)
}

结果

map[name:xiaohong]

转换

方法

func MapTrans[K comparable, V, R any](m map[K]V, fn func(key K, value V) (R, bool)) map[K]R {
    result := make(map[K]R, len(m))
    for k, v := range m {
        if r, ok := fn(k, v); ok {
            result[k] = r
        }
    }
    return result
}

掉用

package test

import (
	"fmt"
	"strings"
	"testing"
	"xh-control-ws/utils"
)

// 普通的测试
func Test01(t *testing.T) {
	userinfo := map[string]string{"name": "xiaoming"}
	userinfo["name"] = "xiaohong"
	userinfo["age"] = "18"

	result := utils.MapTrans(userinfo, func(key string, value string) (string, bool) {
		if key == "name" {
			return strings.ToUpper(value), true
		} else {
			return value + "岁", true
		}
	})
	fmt.Println(result)
}

结果

map[age:18岁 name:XIAOHONG]

其中返回值中的bool,代表对应的key是否保留。