Skip to content

Commit

Permalink
使用sort包,替换框架自己实现的排序
Browse files Browse the repository at this point in the history
  • Loading branch information
steden committed Nov 21, 2024
1 parent 9fd9d59 commit b843f86
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 166 deletions.
129 changes: 25 additions & 104 deletions enumerable.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package collections
import (
"math/rand"
"reflect"
"sort"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -502,28 +503,11 @@ func (receiver Enumerable[T]) OrderBy(fn func(item T) any) Enumerable[T] {
var lst []T
lst = append(lst, *receiver.source...)

// 首先拿数组第0个出来做为左边值
for leftIndex := 0; leftIndex < len(lst); leftIndex++ {
// 拿这个值与后面的值作比较
leftValue := fn(lst[leftIndex])

// 再拿出左边值索引后面的值一一对比
for rightIndex := leftIndex + 1; rightIndex < len(lst); rightIndex++ {
rightValue := fn(lst[rightIndex]) // 这个就是后面的值,会陆续跟数组后面的值做比较
rightItem := lst[rightIndex]

// 后面的值比前面的值小,说明要交换数据
if CompareLeftGreaterThanRight(leftValue, rightValue) {
// 开始交换数据,先从后面交换到前面
for swapIndex := rightIndex; swapIndex > leftIndex; swapIndex-- {
lst[swapIndex] = lst[swapIndex-1]
}
lst[leftIndex] = rightItem
leftValue = fn(lst[leftIndex])
}
}
}

sort.SliceStable(lst, func(i, j int) bool {
leftValue := fn(lst[i])
rightValue := fn(lst[j])
return !CompareLeftGreaterThanRight(leftValue, rightValue)
})
return Enumerable[T]{source: &lst, lock: &sync.RWMutex{}}
}

Expand All @@ -539,23 +523,9 @@ func (receiver Enumerable[T]) OrderByThen(fn func(leftItem, rightItem T) bool) E
var lst []T
lst = append(lst, *receiver.source...)

// 首先拿数组第0个出来做为左边值
for leftIndex := 0; leftIndex < len(lst); leftIndex++ {
// 再拿出左边值索引后面的值一一对比
for rightIndex := leftIndex + 1; rightIndex < len(lst); rightIndex++ {
rightItem := lst[rightIndex]

// 后面的值比前面的值小,说明要交换数据
if fn(lst[leftIndex], rightItem) {
// 开始交换数据,先从后面交换到前面
for swapIndex := rightIndex; swapIndex > leftIndex; swapIndex-- {
lst[swapIndex] = lst[swapIndex-1]
}
lst[leftIndex] = rightItem
}
}
}

sort.SliceStable(lst, func(i, j int) bool {
return !fn(lst[i], lst[j])
})
return Enumerable[T]{source: &lst, lock: &sync.RWMutex{}}
}

Expand All @@ -564,34 +534,18 @@ func (receiver Enumerable[T]) OrderByItem() Enumerable[T] {
if receiver.lock == nil {
return receiver
}

receiver.lock.RLock()
defer receiver.lock.RUnlock()

var lst []T
lst = append(lst, *receiver.source...)

// 首先拿数组第0个出来做为左边值
for leftIndex := 0; leftIndex < len(lst); leftIndex++ {
// 拿这个值与后面的值作比较
leftValue := lst[leftIndex]

// 再拿出左边值索引后面的值一一对比
for rightIndex := leftIndex + 1; rightIndex < len(lst); rightIndex++ {
rightValue := lst[rightIndex] // 这个就是后面的值,会陆续跟数组后面的值做比较
rightItem := lst[rightIndex]

// 后面的值比前面的值小,说明要交换数据
if CompareLeftGreaterThanRight(leftValue, rightValue) {
// 开始交换数据,先从后面交换到前面
for swapIndex := rightIndex; swapIndex > leftIndex; swapIndex-- {
lst[swapIndex] = lst[swapIndex-1]
}
lst[leftIndex] = rightItem
leftValue = lst[leftIndex]
}
}
}

sort.SliceStable(lst, func(i, j int) bool {
leftValue := lst[i]
rightValue := lst[j]
return !CompareLeftGreaterThanRight(leftValue, rightValue)
})
return Enumerable[T]{source: &lst, lock: &sync.RWMutex{}}
}

Expand All @@ -607,28 +561,11 @@ func (receiver Enumerable[T]) OrderByDescending(fn func(item T) any) Enumerable[
var lst []T
lst = append(lst, *receiver.source...)

// 首先拿数组第0个出来做为左边值
for leftIndex := 0; leftIndex < len(lst); leftIndex++ {
// 拿这个值与后面的值作比较
leftValue := fn(lst[leftIndex])

// 再拿出左边值索引后面的值一一对比
for rightIndex := leftIndex + 1; rightIndex < len(lst); rightIndex++ {
rightValue := fn(lst[rightIndex]) // 这个就是后面的值,会陆续跟数组后面的值做比较
rightItem := lst[rightIndex]

// 后面的值比前面的值小,说明要交换数据
if !CompareLeftGreaterThanRight(leftValue, rightValue) {
// 开始交换数据,先从后面交换到前面
for swapIndex := rightIndex; swapIndex > leftIndex; swapIndex-- {
lst[swapIndex] = lst[swapIndex-1]
}
lst[leftIndex] = rightItem
leftValue = fn(lst[leftIndex])
}
}
}

sort.SliceStable(lst, func(i, j int) bool {
leftValue := fn(lst[i])
rightValue := fn(lst[j])
return CompareLeftGreaterThanRight(leftValue, rightValue)
})
return Enumerable[T]{source: &lst, lock: &sync.RWMutex{}}
}

Expand All @@ -644,27 +581,11 @@ func (receiver Enumerable[T]) OrderByDescendingItem() Enumerable[T] {
var lst []T
lst = append(lst, *receiver.source...)

// 首先拿数组第0个出来做为左边值
for leftIndex := 0; leftIndex < len(lst); leftIndex++ {
// 拿这个值与后面的值作比较
leftValue := lst[leftIndex]

// 再拿出左边值索引后面的值一一对比
for rightIndex := leftIndex + 1; rightIndex < len(lst); rightIndex++ {
rightValue := lst[rightIndex] // 这个就是后面的值,会陆续跟数组后面的值做比较
rightItem := lst[rightIndex]

// 后面的值比前面的值小,说明要交换数据
if !CompareLeftGreaterThanRight(leftValue, rightValue) {
// 开始交换数据,先从后面交换到前面
for swapIndex := rightIndex; swapIndex > leftIndex; swapIndex-- {
lst[swapIndex] = lst[swapIndex-1]
}
lst[leftIndex] = rightItem
leftValue = lst[leftIndex]
}
}
}
sort.SliceStable(lst, func(i, j int) bool {
leftValue := lst[i]
rightValue := lst[j]
return CompareLeftGreaterThanRight(leftValue, rightValue)
})
return Enumerable[T]{source: &lst, lock: &sync.RWMutex{}}
}

Expand Down
65 changes: 3 additions & 62 deletions test/enumerable_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package test

import (
"github.com/farseer-go/collections"
"github.com/stretchr/testify/assert"
"math/rand"
"sync"
"testing"
"time"

"github.com/farseer-go/collections"
"github.com/stretchr/testify/assert"
)

func Test_enumerable_Any(t *testing.T) {
Expand Down Expand Up @@ -306,66 +307,6 @@ func Test_enumerable_GroupBy(t *testing.T) {
})
}

func Test_enumerable_OrderBy(t *testing.T) {
lst := collections.NewList(3, 5, 6, 2, 1, 8, 7, 4)
item := lst.OrderBy(func(item int) any {
return item
}).ToArray()

assert.Equal(t, item[0], 1)
assert.Equal(t, item[1], 2)
assert.Equal(t, item[2], 3)
assert.Equal(t, item[3], 4)
assert.Equal(t, item[4], 5)
assert.Equal(t, item[5], 6)
assert.Equal(t, item[6], 7)
assert.Equal(t, item[7], 8)
}

func Test_enumerable_OrderByItem(t *testing.T) {
lst := collections.NewList(3, 5, 6, 2, 1, 8, 7, 4)
item := lst.OrderByItem().ToArray()

assert.Equal(t, item[0], 1)
assert.Equal(t, item[1], 2)
assert.Equal(t, item[2], 3)
assert.Equal(t, item[3], 4)
assert.Equal(t, item[4], 5)
assert.Equal(t, item[5], 6)
assert.Equal(t, item[6], 7)
assert.Equal(t, item[7], 8)
}

func Test_enumerable_OrderByDescending(t *testing.T) {
lst := collections.NewList(3, 5, 6, 2, 1, 8, 7, 4)
item := lst.OrderByDescending(func(item int) any {
return item
}).ToArray()

assert.Equal(t, item[0], 8)
assert.Equal(t, item[1], 7)
assert.Equal(t, item[2], 6)
assert.Equal(t, item[3], 5)
assert.Equal(t, item[4], 4)
assert.Equal(t, item[5], 3)
assert.Equal(t, item[6], 2)
assert.Equal(t, item[7], 1)
}

func Test_enumerable_OrderByDescendingItem(t *testing.T) {
lst := collections.NewList(3, 5, 6, 2, 1, 8, 7, 4)
item := lst.OrderByDescendingItem().ToArray()

assert.Equal(t, item[0], 8)
assert.Equal(t, item[1], 7)
assert.Equal(t, item[2], 6)
assert.Equal(t, item[3], 5)
assert.Equal(t, item[4], 4)
assert.Equal(t, item[5], 3)
assert.Equal(t, item[6], 2)
assert.Equal(t, item[7], 1)
}

func Test_enumerable_Select(t *testing.T) {
lst := collections.NewList("1", "", "2")
var arr []string
Expand Down
107 changes: 107 additions & 0 deletions test/sort_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package test

import (
"math/rand"
"testing"

"github.com/farseer-go/collections"
"github.com/stretchr/testify/assert"
)

func Test_enumerable_OrderBy(t *testing.T) {
lst := collections.NewList(3, 5, 6, 2, 1, 8, 7, 4)
item := lst.OrderBy(func(item int) any {
return item
}).ToArray()

assert.Equal(t, item[0], 1)
assert.Equal(t, item[1], 2)
assert.Equal(t, item[2], 3)
assert.Equal(t, item[3], 4)
assert.Equal(t, item[4], 5)
assert.Equal(t, item[5], 6)
assert.Equal(t, item[6], 7)
assert.Equal(t, item[7], 8)
}

func Test_enumerable_OrderByThen(t *testing.T) {
lst := collections.NewList(3, 5, 6, 2, 1, 8, 7, 4)
item := lst.OrderByThen(func(leftItem, rightItem int) bool {
return leftItem > rightItem
}).ToArray()

assert.Equal(t, item[0], 1)
assert.Equal(t, item[1], 2)
assert.Equal(t, item[2], 3)
assert.Equal(t, item[3], 4)
assert.Equal(t, item[4], 5)
assert.Equal(t, item[5], 6)
assert.Equal(t, item[6], 7)
assert.Equal(t, item[7], 8)
}

func Test_enumerable_OrderByItem(t *testing.T) {
lst := collections.NewList(3, 5, 6, 2, 1, 8, 7, 4)
item := lst.OrderByItem().ToArray()

assert.Equal(t, item[0], 1)
assert.Equal(t, item[1], 2)
assert.Equal(t, item[2], 3)
assert.Equal(t, item[3], 4)
assert.Equal(t, item[4], 5)
assert.Equal(t, item[5], 6)
assert.Equal(t, item[6], 7)
assert.Equal(t, item[7], 8)
}

func Test_enumerable_OrderByDescending(t *testing.T) {
lst := collections.NewList(3, 5, 6, 2, 1, 8, 7, 4)
item := lst.OrderByDescending(func(item int) any {
return item
}).ToArray()

assert.Equal(t, item[0], 8)
assert.Equal(t, item[1], 7)
assert.Equal(t, item[2], 6)
assert.Equal(t, item[3], 5)
assert.Equal(t, item[4], 4)
assert.Equal(t, item[5], 3)
assert.Equal(t, item[6], 2)
assert.Equal(t, item[7], 1)
}

func Test_enumerable_OrderByDescendingItem(t *testing.T) {
lst := collections.NewList(3, 5, 6, 2, 1, 8, 7, 4)
item := lst.OrderByDescendingItem().ToArray()

assert.Equal(t, item[0], 8)
assert.Equal(t, item[1], 7)
assert.Equal(t, item[2], 6)
assert.Equal(t, item[3], 5)
assert.Equal(t, item[4], 4)
assert.Equal(t, item[5], 3)
assert.Equal(t, item[6], 2)
assert.Equal(t, item[7], 1)
}

type family struct {
Name string
Age int
}

// BenchmarkOrderBy-10 2 659323792 ns/op 245808 B/op 3 allocs/op
// BenchmarkOrderBy-10 248 4913683 ns/op 245947 B/op 6 allocs/op
func BenchmarkOrderBy(b *testing.B) {
lst := collections.NewList[family]()
for i := 0; i < 10000; i++ {
lst.Add(family{"", rand.Intn(100)})
}

b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
lst.OrderBy(func(item family) any {
return item.Age
})
}
}

0 comments on commit b843f86

Please sign in to comment.