Go泛型实战:实现通用的Slice库(ForEach()、Map()、Filter()、Reduce()等)

3,682 阅读2分钟

前言

就在两天前,Go刚刚发布了1.18的Beta 1版本,正式支持泛型,这让实现一个泛型的Slice库变得可能,因此我马上尝试了一下,对常用的slice的操作进行封装。

如果需要了解Go泛型的基本语法,可以看这篇文章:Go泛型快速入门

下面代码需要Go版本1.18 Beta 1及以上

ForEach

对每个元素执行action函数

func ForEach[T any](slice []T, action func(T)) {
   for _, item := range slice {
      action(item)
   }
}

Map

把T1类型的slice转换成T2类型的slice

func Map[T1 any, T2 any](slice []T1, mapper func(T1) T2) []T2 {
   mapped := make([]T2, 0, len(slice))
   for _, item := range slice {
      mapped = append(mapped, mapper(item))
   }
   return mapped
}

Filter

过滤不满足条件的元素

func Filter[T any](slice []T, condition func(T) bool) []T {
   var filtered []T
   for _, item := range slice {
      if condition(item) {
         filtered = append(filtered, item)
      }
   }
   return filtered
}

Reduce

把slice转换成一个值

func Reduce[T any](slice []T, reduce func(cur T, item T) T, init T) T {
   for i := 0; i < len(slice); i++ {
      init = reduce(init, slice[i])
   }
   return init
}

Every

是否每个元素都满足条件

func Every[T any](slice []T, condition func(T) bool) bool {
   for _, item := range slice {
      if !condition(item) {
         return false
      }
   }
   return true
}

Find

返回第一个满足条件的元素

func Find[T any](slice []T, condition func(T) bool) (T, bool) {
   for _, item := range slice {
      if condition(item) {
         return item, true
      }
   }
   var t T
   return t, false
}

FindIndex

返回第一个满足条件的元素的下标

func FindIndex[T any](slice []T, condition func(T) bool) int {
   for i, item := range slice {
      if condition(item) {
         return i
      }
   }
   return -1
}

IndexOf

返回第一个值相等的元素的下标

func IndexOf[T comparable](slice []T, item T) int {
   for i := 0; i < len(slice); i++ {
      if slice[i] == item {
         return i
      }
   }
   return -1
}

LastIndexOf

返回最后一个值相等的元素的下标

func LastIndexOf[T comparable](slice []T, item T) int {
   for i := len(slice) - 1; i >= 0; i-- {
      if slice[i] == item {
         return i
      }
   }
   return -1
}

ReduceRight

把slice转换成一个值,从右边开始

func ReduceRight[T any](slice []T, reduce func(cur T, item T) T, init T) T {
   for i := len(slice) - 1; i >= 0; i-- {
      init = reduce(init, slice[i])
   }
   return init
}

Reverse

颠倒slice

func Reverse[T any](slice []T) []T {
   reversed := make([]T, 0, len(slice))
   for i := len(slice) - 1; i >= 0; i-- {
      reversed = append(reversed, slice[i])
   }
   return reversed
}

Shift

移除第一个元素

func Shift[T any](slice []T) ([]T, T) {
   t := slice[0]
   return slice[1:], t
}

Shuffle

打乱slice

func Shuffle[T any](slice []T) {
   for i := 0; i < len(slice); i++ {
      rand.Shuffle(len(slice), func(i, j int) {
         slice[i], slice[j] = slice[j], slice[i]
      })
   }
}

Some

是否有元素满足条件

func Some[T any](slice []T, condition func(T) bool) bool {
   for _, item := range slice {
      if condition(item) {
         return true
      }
   }
   return false
}

Unshift

在slice头部添加元素

func Unshift[T any](slice []T, items ...T) []T {
   return append(items, slice...)
}

完整代码

Github:github.com/jiaxwu/slic…

也可以直接:go get github.com/jiaxwu/slices 导入