/*
    JDK8 Stream 是一个支持泛型和函数式数据流,使用起来非常强大方便。最近在学习 go 语言我就用 go 模仿了一下类似的功能,
    由于 go 对泛型、函数式的支持比较有限,感觉泛型和函数式这一块实现起来有些别扭,可能是我不会用,不当之处请高手指点。

    Stream 具备部分与整体一致的结构设计,可很方便用来实现各种递归算法,尾部有一个Nil作为递归跳出点。
    “左折叠”和“右折叠” 是非常强大的操作,大多数其它操作都可以通过折叠实现的,
    Stream 自身的很多方法也是通过折叠操作实现的,如反向、合并、筛选、排序等。
    Stream 的参数类型为空接口,支持泛型类型。
    Stream 提供的很多方法都是接受函数作为参数的 “高阶方法”,比如:filter ,map ,reduce

    Stream 支持用数学归纳法生成各种数列,步骤非常简单:
    1、给出一个递归结束的值. 例如: f(1) =1
    2、指定 f(n-1).
    3、用f(n-1)定义f(n). 例如:f(n)= f(n-1) + 1
*/
package stream

import (
    "fmt"
    "strings"
)

//泛型类型定义
type T    interface {}
type U    interface {}

//流计算数据结构定义
type Stream    struct {
    Head     T
    Tail     *Stream
    Length   int
    NotEmpty bool
}

var Nil = Stream{}

func Generate(r Stream, f    func (Stream) T, m int) Stream {

    if m == 1 {
        return r
    }    else {
        return Generate(New(f(r), &r), f, m-1)
    }
}

func New(head T, tail *Stream) Stream {
    return Stream{head, tail, tail.Length + 1, true}
}

func (s Stream) Add(i T) Stream {
    return New(i, &s)
}

func (s Stream) Addall(i ...T) Stream {
    for _, v :=    range i {
        s = s.Add(v)
    }
    return s
}

//左折叠 用于实现 reduce 的功能
func (s Stream) FoldLeft(i U, f    func (U, T) U) U {
    if s.NotEmpty {
        return s.Tail.FoldLeft(f(i, s.Head), f)
    }    else {
        return i
    }
}

//右折叠
func (s Stream) FoldRight(i U, f    func (U, T) U) U {
    if s.NotEmpty {
        return f(s.Tail.FoldRight(i, f), s.Head)
    }    else {
        return i
    }
}

//合并两个 Stream
func (s Stream) Merge(t Stream) Stream {
    if t.NotEmpty {
        return t.FoldRight(s,    func (u U, t T) U {
            return u.(Stream).Add(t)
        }).(Stream)

    }    else {
        return s
    }
}

//倒序
func (s Stream) Reverse() Stream {
    return s.FoldLeft(Nil,    func (u U, t T) U {
        return u.(Stream).Add(t)
    }).(Stream)
}

//Map
func (s Stream) Map(f    func (T) U) Stream {
    return s.FoldRight(Nil,    func (u U, t T) U {
        return u.(Stream).Add(f(t))
    }).(Stream)
}

//Reduce
func (s Stream) Reduce(i T, f    func (T, T) T) T {
    if s.NotEmpty {
        return s.Tail.Reduce(f(i, s.Head), f)
    }    else {
        return i
    }
}

//过滤
func (s Stream) Filter(f    func (T) bool) Stream {
    return s.FoldRight(Nil,    func (u U, t T) U {
        if f(t) {
            return u.(Stream).Add(t)
        }    else {
            return u
        }
    }).(Stream)
}

//归并排序
func (s Stream) Sort(c    func (T,T) bool) Stream {

    n := s.Length / 2

    if n == 0 {
        return s
    }   else {
        x,y := split(s, Nil, n)
        return merge(x.Sort(c),y.Sort(c),c)
    }
}


func split(x,y Stream , n int) (Stream,Stream) {

    if (n == 0 || !x.NotEmpty) {
        return x,y
    }
    return split(*x.Tail, y.Add(x.Head), n - 1);
}


func merge(x,y Stream , c    func (T,T) bool) Stream {

    if (!x.NotEmpty){
        return y;
    }
    if (!y.NotEmpty){
        return x;
    }
    if c(x.Head,y.Head) {
        return merge(*x.Tail, y, c).Add(x.Head)
    }   else {
        return merge(x, *y.Tail, c).Add(y.Head);
    }
}

//格式化显示 Stream 的所有项
func (s Stream) ToString() string {
    return "{" + strings.Join(s.FoldRight([]string{},    func (u U, t T) U {
        return append(u.([]string), fmt.Sprintf(   "%v" , t))
    }).([]string),    "," ) +    "}"
}

  使用的样例

package main

import (
    "fmt"
    .   "./stream"
    "strings"
)

func main() {

    x := Generate(Nil.Add(1),  func (s Stream) T {  return s.Head.(int)+1},50)   // {1,2,3,...,48,49,50}
    x = x.Map(  func (t T) U {
        p := t.(int)   //平方映射
        return p * p
    }).Filter(  func (t T) bool {
        return t.(int) % 2 == 0   //偶数过滤
    })

    //计算所有项的和
    fmt.Printf(  "sum %s = %d\n" ,x.ToString(),x.FoldLeft(0,  func (u U, t T) U {
        return u.(int) + t.(int)
    }))   //22100


    //浮点数列表求和
    y := Nil.Addall(3.5, 4.3, 2.6, 1.1, 7.83, 4.42)
    fmt.Printf(  "%.2f\n" , y.Reduce(0.0,   func (t T, t2 T) T {
        return t.(float64) + t2.(float64)
    }))

   
    //排序
    z := Nil.Addall(4,3,7,6,2,1,9,5,8,0).Sort(  func (x,y T) bool {
        return x.(int) > y.(int)
    })
    fmt.Println(z.ToString())   //{0,1,2,3,4,5,6,7,8,9}


    //列出包含a字符的字符串
    g := Nil.Addall(  "aaa" ,   "bbb" ,   "aba" ,   "ccc" ,   "cbb" ,   "cba" )
    fmt.Println(g.Filter(  func (t T) bool {
        return strings.Contains(t.(string),   "a" )
    }).ToString())

    //生成斐波拉契亚数列 的前 20 项
    fmt.Println(Generate(Nil.Addall(1, 1),   func (s Stream) T {
        return s.Head.(int) + s.Tail.Head.(int)
    }, 19).ToString())


    //通过数列 π = 2 + 2/3 + 2/3*2/5 + 2/3*2/5*3/7  + ... + f(n-1) * n/(2*n+1) 计算圆周率的值
    fmt.Println(Generate(Nil.Add(2.0),   func (s Stream) T {
        n := s.Length
        return s.Head.(float64) * float64(n) / (float64(n)*2 + 1)
    }, 51).Reduce(0.0,   func (t T, t2 T) T {
        return t.(float64) + t2.(float64)
    }))
}

 

 

posted on 2026-10-05 11:31  Freud  阅读(5)  评论(0)    收藏  举报