XArray Guide - zhoudm1743/go-util GitHub Wiki

XArray 是 Go-Util 的核心数组处理工具,基于 Go 泛型设计,提供函数式编程风格的数组操作,让数据处理变得简单而优雅。

🚀 特性亮点

  • 🧩 泛型支持: 完整的类型安全,编译时错误检查
  • 🔄 函数式编程: Map、Filter、Reduce 等高阶函数
  • 🔗 链式调用: 流畅的方法链,提高代码可读性
  • ⚡ 高性能: 原地操作和批量处理优化
  • 📊 丰富功能: 涵盖所有常见数组操作场景
  • 🔧 易扩展: 支持自定义比较和转换函数

📦 基础用法

创建 XArray 对象

import util "github.com/zhoudm1743/go-util"

// 从元素创建
arr := util.Arrays(1, 2, 3, 4, 5)           // XArray[int]
strings := util.Arrays("a", "b", "c")        // XArray[string]

// 从切片创建
slice := []int{1, 2, 3, 4, 5}
arr2 := util.ArraysFromSlice(slice)

// 创建指定类型的数组
mixed := util.NewArray[interface{}]()
mixed.Append(1, "hello", 3.14, true)

// 创建预分配容量的数组
largeArr := util.NewArrayWithCapacity[int](1000)

// 空数组
empty := util.NewArray[string]()

基础信息获取

arr := util.Arrays(1, 2, 3, 4, 5)

// 长度和容量
fmt.Println(arr.Len())           // 5
fmt.Println(arr.Cap())           // 5 (或更大)

// 状态检查
fmt.Println(arr.IsEmpty())       // false
fmt.Println(arr.IsNotEmpty())    // true

// 转换为切片
slice := arr.ToSlice()           // []int{1, 2, 3, 4, 5}

// 获取底层数据
data := arr.Data()               // []int{1, 2, 3, 4, 5}

📝 元素操作

添加元素

arr := util.NewArray[int]()

// 单个添加
arr.Append(1)                    // [1]
arr.Prepend(0)                   // [0, 1]
arr.Insert(1, 999)               // [0, 999, 1]

// 批量添加
arr.AppendSlice([]int{2, 3, 4})  // [0, 999, 1, 2, 3, 4]
arr.PrependSlice([]int{-2, -1})  // [-2, -1, 0, 999, 1, 2, 3, 4]

// 链式添加
result := util.NewArray[string]().
    Append("hello").
    Append("world").
    Prepend("hi")                // ["hi", "hello", "world"]

删除元素

arr := util.Arrays(1, 2, 3, 4, 5, 3, 6)

// 按索引删除
arr.RemoveAt(0)                  // [2, 3, 4, 5, 3, 6]
arr.RemoveRange(1, 3)            // [2, 5, 3, 6]

// 按值删除
arr.Remove(3)                    // [2, 5, 6] (删除第一个3)
arr.RemoveAll(3)                 // [2, 5, 6] (删除所有3)

// 删除重复项
arr2 := util.Arrays(1, 2, 2, 3, 3, 3, 4)
unique := arr2.Distinct()        // [1, 2, 3, 4]

// 清空数组
arr.Clear()                      // []

访问元素

arr := util.Arrays("apple", "banana", "cherry", "date")

// 索引访问
first := arr.Get(0)              // "apple"
last := arr.Get(-1)              // "date" (支持负索引)

// 安全访问
value, ok := arr.SafeGet(10)     // "", false (越界返回零值)
valueOrDefault := arr.GetOr(10, "default") // "default"

// 查找元素
index := arr.IndexOf("banana")   // 1
lastIndex := arr.LastIndexOf("banana") // 1
found := arr.Contains("cherry")  // true

// 范围访问
subArray := arr.Slice(1, 3)      // ["banana", "cherry"]
head := arr.Head(2)              // ["apple", "banana"]
tail := arr.Tail(2)              // ["cherry", "date"]

🔄 函数式编程

Map 转换

numbers := util.Arrays(1, 2, 3, 4, 5)

// 基础转换
squares := numbers.Map(func(n int) int {
    return n * n
})  // [1, 4, 9, 16, 25]

// 类型转换
strings := numbers.Map(func(n int) string {
    return fmt.Sprintf("num_%d", n)
})  // ["num_1", "num_2", "num_3", "num_4", "num_5"]

// 带索引的转换
indexed := numbers.MapWithIndex(func(i, n int) string {
    return fmt.Sprintf("%d:%d", i, n)
})  // ["0:1", "1:2", "2:3", "3:4", "4:5"]

// 原地转换 (性能更好)
numbers.MapInPlace(func(n int) int {
    return n * 2
})  // [2, 4, 6, 8, 10]

Filter 过滤

numbers := util.Arrays(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 基础过滤
evens := numbers.Filter(func(n int) bool {
    return n%2 == 0
})  // [2, 4, 6, 8, 10]

// 带索引的过滤
filteredWithIndex := numbers.FilterWithIndex(func(i, n int) bool {
    return i%2 == 0 && n > 3  // 偶数索引且值大于3
})  // [5, 7, 9]

// 原地过滤
numbers.FilterInPlace(func(n int) bool {
    return n <= 5
})  // [1, 2, 3, 4, 5]

// 拒绝过滤 (排除满足条件的)
odds := util.Arrays(1, 2, 3, 4, 5).Reject(func(n int) bool {
    return n%2 == 0
})  // [1, 3, 5]

Reduce 聚合

numbers := util.Arrays(1, 2, 3, 4, 5)

// 基础聚合
sum := numbers.Reduce(func(acc, curr int) int {
    return acc + curr
}, 0)  // 15

product := numbers.Reduce(func(acc, curr int) int {
    return acc * curr
}, 1)  // 120

// 字符串连接
words := util.Arrays("hello", "world", "go")
sentence := words.Reduce(func(acc, curr string) string {
    if acc == "" {
        return curr
    }
    return acc + " " + curr
}, "")  // "hello world go"

// 查找最大值
max := numbers.Reduce(func(acc, curr int) int {
    if curr > acc {
        return curr
    }
    return acc
}, numbers.Get(0))  // 5

ForEach 遍历

fruits := util.Arrays("apple", "banana", "cherry")

// 基础遍历
fruits.ForEach(func(i int, fruit string) bool {
    fmt.Printf("%d: %s\n", i, fruit)
    return true  // 继续遍历
})

// 条件中断
fruits.ForEach(func(i int, fruit string) bool {
    fmt.Printf("%s\n", fruit)
    return fruit != "banana"  // 遇到banana时停止
})

// 简单遍历 (无索引)
fruits.Each(func(fruit string) {
    fmt.Println(fruit)
})

🔍 查找和匹配

查找操作

numbers := util.Arrays(1, 2, 3, 4, 5, 6)

// 查找第一个匹配
first, found := numbers.Find(func(n int) bool {
    return n > 3
})  // 4, true

// 查找最后一个匹配
last, found := numbers.FindLast(func(n int) bool {
    return n%2 == 0
})  // 6, true

// 查找索引
index := numbers.FindIndex(func(n int) bool {
    return n > 3
})  // 3

// 查找所有匹配
allEvens := numbers.FindAll(func(n int) bool {
    return n%2 == 0
})  // [2, 4, 6]

条件检查

numbers := util.Arrays(1, 2, 3, 4, 5)

// 全部满足
allPositive := numbers.All(func(n int) bool {
    return n > 0
})  // true

// 任意满足
anyEven := numbers.Any(func(n int) bool {
    return n%2 == 0
})  // true

// 无任何满足
noneNegative := numbers.None(func(n int) bool {
    return n < 0
})  // true

// 计数
evenCount := numbers.Count(func(n int) bool {
    return n%2 == 0
})  // 2

📊 排序和分组

排序操作

// 基础排序 (需要实现 Ordered 约束)
numbers := util.Arrays(5, 2, 8, 1, 9, 3)
sorted := numbers.Sort()                 // [1, 2, 3, 5, 8, 9]
reversed := numbers.SortDesc()           // [9, 8, 5, 3, 2, 1]

// 原地排序
numbers.SortInPlace()                    // [1, 2, 3, 5, 8, 9]
numbers.ReverseInPlace()                 // [9, 8, 5, 3, 2, 1]

// 自定义排序
users := util.Arrays(
    User{Name: "Alice", Age: 30},
    User{Name: "Bob", Age: 25},
    User{Name: "Charlie", Age: 35},
)

// 按年龄排序
sortedByAge := users.SortBy(func(u User) int {
    return u.Age
})

// 自定义比较函数
sortedByName := users.SortWith(func(a, b User) bool {
    return a.Name < b.Name
})

// 检查是否已排序
isSorted := numbers.IsSorted()           // true

分组操作

numbers := util.Arrays(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 按条件分组
grouped := numbers.GroupBy(func(n int) string {
    if n%2 == 0 {
        return "even"
    }
    return "odd"
})  // map[string][]int{"even": [2,4,6,8,10], "odd": [1,3,5,7,9]}

// 分块处理
chunks := numbers.Chunk(3)               // [1,2,3], [4,5,6], [7,8,9], [10](/zhoudm1743/go-util/wiki/1,2,3],-[4,5,6],-[7,8,9],-[10)

// 分区
evens, odds := numbers.Partition(func(n int) bool {
    return n%2 == 0
})  // evens: [2,4,6,8,10], odds: [1,3,5,7,9]

🔗 数组组合

连接操作

arr1 := util.Arrays(1, 2, 3)
arr2 := util.Arrays(4, 5, 6)
arr3 := util.Arrays(7, 8, 9)

// 连接数组
combined := arr1.Concat(arr2)            // [1, 2, 3, 4, 5, 6]

// 多数组连接
multiCombined := arr1.ConcatMultiple(arr2, arr3) // [1,2,3,4,5,6,7,8,9]

// 原地连接
arr1.ConcatInPlace(arr2)                 // arr1 变为 [1,2,3,4,5,6]

集合操作

set1 := util.Arrays(1, 2, 3, 4, 5)
set2 := util.Arrays(3, 4, 5, 6, 7)

// 交集
intersection := set1.Intersect(set2)     // [3, 4, 5]

// 并集
union := set1.Union(set2)                // [1, 2, 3, 4, 5, 6, 7]

// 差集
difference := set1.Difference(set2)      // [1, 2]

// 对称差集
symmetricDiff := set1.SymmetricDifference(set2) // [1, 2, 6, 7]

// 子集检查
isSubset := util.Arrays(1, 2).IsSubsetOf(set1)  // true

🔄 数组变换

形状变换

numbers := util.Arrays(1, 2, 3, 4, 5, 6)

// 反转
reversed := numbers.Reverse()            // [6, 5, 4, 3, 2, 1]

// 洗牌
shuffled := numbers.Shuffle()            // [3, 1, 6, 2, 5, 4] (随机)

// 旋转
rotated := numbers.Rotate(2)             // [3, 4, 5, 6, 1, 2]
rotatedLeft := numbers.RotateLeft(2)     // [5, 6, 1, 2, 3, 4]

// 填充
filled := util.NewArray[int]().Fill(0, 5) // [0, 0, 0, 0, 0]

// 重复
repeated := util.Arrays(1, 2).Repeat(3)  // [1, 2, 1, 2, 1, 2]

抽样和选择

numbers := util.Arrays(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 取前N个
first3 := numbers.Take(3)                // [1, 2, 3]

// 跳过前N个
skip3 := numbers.Skip(3)                 // [4, 5, 6, 7, 8, 9, 10]

// 取满足条件的前N个
takeWhile := numbers.TakeWhile(func(n int) bool {
    return n < 5
})  // [1, 2, 3, 4]

// 跳过满足条件的元素
skipWhile := numbers.SkipWhile(func(n int) bool {
    return n < 5
})  // [5, 6, 7, 8, 9, 10]

// 随机抽样
sample := numbers.Sample(3)              // 随机选择3个元素

📈 统计和聚合

数值统计

numbers := util.Arrays(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

// 基础统计
sum := numbers.Sum()                     // 55 (需要数值类型)
avg := numbers.Average()                 // 5.5
min := numbers.Min()                     // 1
max := numbers.Max()                     // 10

// 中位数和众数
median := numbers.Median()               // 5.5
mode := numbers.Mode()                   // 可能返回多个值

// 方差和标准差
variance := numbers.Variance()           // 8.25
stdDev := numbers.StandardDeviation()    // 2.87

// 自定义聚合
maxLength := util.Arrays("a", "bb", "ccc", "d").
    MaxBy(func(s string) int {
        return len(s)
    })  // "ccc"

频率分析

grades := util.Arrays("A", "B", "A", "C", "B", "A", "D")

// 频率统计
frequency := grades.Frequency()          // map[string]int{"A":3, "B":2, "C":1, "D":1}

// 最频繁的元素
mostFrequent := grades.MostFrequent()    // "A"

// 按频率排序
sortedByFreq := grades.SortByFrequency() // ["A", "A", "A", "B", "B", "C", "D"]

🔧 高级功能

自定义比较和相等

type Person struct {
    Name string
    Age  int
}

people := util.Arrays(
    Person{"Alice", 30},
    Person{"Bob", 25},
    Person{"Alice", 30},
)

// 自定义相等比较
unique := people.DistinctBy(func(p Person) string {
    return p.Name  // 按姓名去重
})

// 自定义比较函数
sorted := people.SortWith(func(a, b Person) bool {
    if a.Age != b.Age {
        return a.Age < b.Age
    }
    return a.Name < b.Name  // 年龄相同时按姓名排序
})

并行处理

largeNumbers := util.NewArray[int]()
for i := 0; i < 1000000; i++ {
    largeNumbers.Append(i)
}

// 并行映射
results := largeNumbers.ParallelMap(func(n int) int {
    return n * n  // 计算平方
}, 4)  // 使用4个goroutine

// 并行过滤
filtered := largeNumbers.ParallelFilter(func(n int) bool {
    return n%2 == 0
}, 4)  // 使用4个goroutine

// 并行聚合
sum := largeNumbers.ParallelReduce(func(acc, curr int) int {
    return acc + curr
}, 0, 4)  // 使用4个goroutine

管道操作

// 复杂的数据处理管道
result := util.Arrays(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).
    Filter(func(n int) bool { return n%2 == 0 }).     // 过滤偶数
    Map(func(n int) int { return n * 3 }).            // 乘以3
    Filter(func(n int) bool { return n > 10 }).       // 大于10
    Take(3).                                          // 取前3个
    Sort().                                           // 排序
    ToSlice()                                         // 转为切片

fmt.Println(result)  // [12, 18, 24]

🚀 性能优化

原地操作

numbers := util.Arrays(5, 2, 8, 1, 9, 3)

// ✅ 原地操作 (更高效)
numbers.SortInPlace()                    // 原地排序
numbers.ReverseInPlace()                 // 原地反转
numbers.FilterInPlace(func(n int) bool {
    return n > 3
})                                       // 原地过滤

// ❌ 创建新数组 (内存开销大)
sorted := numbers.Sort()
reversed := numbers.Reverse()
filtered := numbers.Filter(func(n int) bool {
    return n > 3
})

预分配容量

// ✅ 预分配容量
expectedSize := 10000
arr := util.NewArrayWithCapacity[int](expectedSize)
for i := 0; i < expectedSize; i++ {
    arr.Append(i)  // 避免多次扩容
}

// ✅ 批量操作
data := make([]int, 10000)
for i := range data {
    data[i] = i
}
arr2 := util.ArraysFromSlice(data)  // 一次性创建

并发处理

// 大数据集并发处理
func ProcessLargeArray(data *util.XArray[int]) *util.XArray[int] {
    workerCount := runtime.NumCPU()
    
    return data.
        ParallelFilter(heavyFilterCondition, workerCount).
        ParallelMap(expensiveTransform, workerCount).
        ParallelSort(workerCount)
}

🔍 实际应用场景

数据清洗

// 用户数据清洗
func CleanUserData(users []User) []User {
    return util.ArraysFromSlice(users).
        Filter(func(u User) bool {
            return u.Email != "" && u.Age > 0  // 过滤无效数据
        }).
        DistinctBy(func(u User) string {
            return u.Email  // 按邮箱去重
        }).
        SortBy(func(u User) string {
            return u.Name  // 按姓名排序
        }).
        ToSlice()
}

// CSV数据处理
func ProcessCSVData(records [][]string) []map[string]string {
    if len(records) == 0 {
        return nil
    }
    
    headers := records[0]
    data := records[1:]
    
    return util.ArraysFromSlice(data).
        Filter(func(record []string) bool {
            return len(record) == len(headers)  // 过滤格式错误的行
        }).
        Map(func(record []string) map[string]string {
            result := make(map[string]string)
            for i, value := range record {
                result[headers[i]] = strings.TrimSpace(value)
            }
            return result
        }).
        ToSlice()
}

数据分析

// 销售数据分析
type Sale struct {
    Product  string
    Amount   float64
    Date     time.Time
    Category string
}

func AnalyzeSales(sales []Sale) map[string]float64 {
    return util.ArraysFromSlice(sales).
        Filter(func(s Sale) bool {
            return s.Amount > 0  // 过滤无效销售
        }).
        GroupBy(func(s Sale) string {
            return s.Category  // 按类别分组
        }).
        MapValues(func(salesInCategory []Sale) float64 {
            return util.ArraysFromSlice(salesInCategory).
                Map(func(s Sale) float64 { return s.Amount }).
                Sum()  // 计算每个类别的总销售额
        })
}

// 学生成绩统计
func AnalyzeGrades(students []Student) GradeStats {
    scores := util.ArraysFromSlice(students).
        Map(func(s Student) float64 { return s.Score }).
        Filter(func(score float64) bool { return score >= 0 })
    
    return GradeStats{
        Average:  scores.Average(),
        Median:   scores.Median(),
        Min:      scores.Min(),
        Max:      scores.Max(),
        PassRate: scores.Count(func(s float64) bool { return s >= 60 }) / float64(scores.Len()),
    }
}

API 响应处理

// API响应数据转换
func TransformAPIResponse(response APIResponse) []DisplayItem {
    return util.ArraysFromSlice(response.Items).
        Filter(func(item APIItem) bool {
            return item.Status == "active"  // 只显示活跃项目
        }).
        Map(func(item APIItem) DisplayItem {
            return DisplayItem{
                ID:          item.ID,
                Title:       strings.Title(item.Name),
                Description: util.Str(item.Description).Truncate(100).String(),
                Tags:        item.Tags,
            }
        }).
        SortBy(func(item DisplayItem) string {
            return item.Title  // 按标题排序
        }).
        Take(20).  // 限制返回数量
        ToSlice()
}

// 批量数据验证
func ValidateBatchData(data []UserInput) ([]ValidUser, []ValidationError) {
    results := util.ArraysFromSlice(data).
        MapWithIndex(func(i int, input UserInput) ValidationResult {
            if err := validateUser(input); err != nil {
                return ValidationResult{Index: i, Error: err}
            }
            return ValidationResult{Index: i, User: transformToUser(input)}
        })
    
    errors := results.
        Filter(func(r ValidationResult) bool { return r.Error != nil }).
        Map(func(r ValidationResult) ValidationError {
            return ValidationError{Index: r.Index, Message: r.Error.Error()}
        }).ToSlice()
    
    users := results.
        Filter(func(r ValidationResult) bool { return r.Error == nil }).
        Map(func(r ValidationResult) ValidUser { return r.User }).
        ToSlice()
    
    return users, errors
}

📊 性能基准

基准测试结果

操作类型                    元素数量      性能指标
基础操作 (Append/Get)       10万         微秒级
Map 转换                   10万         毫秒级
Filter 过滤                10万         毫秒级
Sort 排序                  10万         20-50ms
Reduce 聚合                100万        100ms
并行操作 (4核)             100万        25-30ms

内存使用优化

// 基准测试示例
func BenchmarkArrayOperations(b *testing.B) {
    data := make([]int, 10000)
    for i := range data {
        data[i] = rand.Intn(1000)
    }
    arr := util.ArraysFromSlice(data)
    
    b.ResetTimer()
    b.ReportAllocs()
    
    for i := 0; i < b.N; i++ {
        result := arr.
            Filter(func(n int) bool { return n%2 == 0 }).
            Map(func(n int) int { return n * 2 }).
            Take(100).
            ToSlice()
        _ = result
    }
}

// 结果示例:
// BenchmarkArrayOperations-8    1000    1.2ms/op    156KB/op    15 allocs/op

🎯 最佳实践

1. 性能优化

// ✅ 使用原地操作
arr.FilterInPlace(condition)
arr.SortInPlace()

// ✅ 预分配容量
arr := util.NewArrayWithCapacity[int](expectedSize)

// ✅ 并行处理大数据
arr.ParallelMap(transform, runtime.NumCPU())

// ❌ 避免频繁的小数组操作
for i := 0; i < 1000; i++ {
    arr := util.Arrays(i)  // 每次都创建新数组
}

2. 内存管理

// ✅ 及时释放大数组
defer func() { largeArray = nil }()

// ✅ 使用流式处理
result := processInChunks(data, 1000)

// ✅ 选择合适的操作
if needNewArray {
    filtered := arr.Filter(condition)  // 创建新数组
} else {
    arr.FilterInPlace(condition)       // 原地修改
}

3. 可读性优化

// ✅ 清晰的函数式管道
processedData := util.ArraysFromSlice(rawData).
    Filter(isValid).              // 步骤1:验证数据
    Map(transform).               // 步骤2:转换格式
    GroupBy(categorize).          // 步骤3:分组
    MapValues(aggregate).         // 步骤4:聚合计算
    ToMap()

// ✅ 使用有意义的函数名
isActiveUser := func(u User) bool { return u.Status == "active" }
activeUsers := users.Filter(isActiveUser)

🔗 相关资源

💬 获取帮助

如果您在使用 XArray 时遇到问题:


🎉 现在您已经掌握了 XArray 的强大功能,开始在项目中使用这些优雅的数组操作吧!