go语言学习六 - 自定义类型:Stream

package stream

import (
        "fmt"
        "reflect"
        "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
        }

        return Generate(New(f(r), &r), f, m-1)
}

func From(i ...T) Stream {

        return Nil.Addall(i...)

}

var IntSlice = func(value reflect.Value) U {
        return value.Int()
}

func FromSlice(i T, f func(reflect.Value) U) Stream {

        s := Nil
        v := reflect.ValueOf(i)

        n := v.Len()

        for i := 0; i < n; i++ {
                s = s.Add(f(v.Index(i)))
        }

        return s

}

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)
        }

        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)
        }

        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)

        }

        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(t1,t2 T) T) T {

        if s.NotEmpty {
                return s.Tail.Reduce(f(i, s.Head), f)
        }

        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)
                }

                return u

        }).(Stream)

}

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

        n := s.Length / 2

        if n == 0 {
                return s
        }

        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(t1,t2 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)
        }

        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 (
        "./stream"
        "fmt"
        "strings"
)

func main() {

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

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

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

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

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

        //生成斐波拉契亚数列 的前 20 项
        fmt.Println(stream.Generate(stream.From(1, 1), func(s stream.Stream) 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(stream.Generate(stream.From(2.0), func(s stream.Stream) stream.T {
                n := s.Length
                return s.Head.(float64) * float64(n) / (float64(n)*2 + 1)
        }, 51).Reduce(0.0, func(t, t2 stream.T) stream.T {
                return t.(float64) + t2.(float64)
        }))

        fmt.Println(stream.From(1, 2, 3, 4, 5).Reduce(0, func(t1, t2 stream.T) stream.T {
                return t1.(int) + t2.(int)
        }))

        k := []int{1, 2, 3, 4, 5}
        p := stream.FromSlice(k, stream.IntSlice)

        fmt.Println(p.Reduce(int64(0), func(t1, t2 stream.T) stream.T {
                return t1.(int64) + t2.(int64)
        }))

}

///////////////////////////////////