Skip to content

Commit

Permalink
docs: add reduce, times, sortBy, sortDesc, sortByDesc
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi committed Feb 10, 2022
1 parent 40453f3 commit af5798f
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 8 deletions.
69 changes: 68 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ Equivalent to:
collect.UseSlice([]int{1, 2, 3}).Map(fn).Filter(fn).Reduce(fn).All()
```

**_Note: Since Go 1.18 has not yet been officially released and its language behavior may still change after the release, go-collection is currently for trial use only. If you have additional questions or suggestions, please [file an issue](https://github.com/sxyazi/go-collection/issues/new)._**

**_Note: Go 1.18 Beta 2, released this past week, still has some bugs, so you will need to use the [gotip](https://pkg.go.dev/golang.org/dl/gotip) tool to get the latest master branch of Go when trying out go-collection._**

## Installation

```shell
Expand Down Expand Up @@ -334,6 +338,19 @@ The corresponding chained function is `collect.UseSlice()`

</details>

- `Reduce` reduces the collection to a single value, and the parameters of each iteration are the results of the previous iteration

<details>
<summary>Examples</summary>

```go
collect.Reduce([]int{1, 2, 3}, 100, func(carry, value, key int) int {
return carry + value
}) // 106
```

</details>

- `Count` counts the number of occurrences of each element in the slice

<details>
Expand Down Expand Up @@ -532,6 +549,17 @@ The corresponding chained function is `collect.UseNumber()`,which is a subset

</details>

- `SortDesc` sorts the numbers in the collection in descending order

<details>
<summary>Examples</summary>

```go
collect.SortDesc([]float64{1, -4, 0, -4.3}) // []float64{1, 0, -4, -4.3}
```

</details>

- `Avg` calculates the average

<details>
Expand Down Expand Up @@ -612,7 +640,7 @@ Due to Golang's support for generics, it is [not possible to define generic type

</details>

- `MapKeyBy` retrieves the set with the value of the given key as the identifier (if there are duplicate keys, only the last one will be kept), only maps are supported
- `MapKeyBy` retrieves the collection with the value of the given key as the identifier (if there are duplicate keys, only the last one will be kept), only maps are supported

<details>
<summary>Examples</summary>
Expand Down Expand Up @@ -648,6 +676,45 @@ Due to Golang's support for generics, it is [not possible to define generic type

</details>

- `Times` creates a new collection of slices by calling the callback with specified number of times

<details>
<summary>Examples</summary>

```go
collect.Times(3, func(number int) float64 {
return float64(number) * 3.14
}) // *SliceCollection{[]float64{3.14, 6.28, 9.42}}
```

</details>

- `SortBy` calls a callback for each element and performs an ascending sort by the return value of the callback

<details>
<summary>Examples</summary>

```go
collect.SortBy([]int{2, 1, 3}, func(item, index int) string {
return strconv.Itoa(item)
}) // *SliceCollection{[]int{1, 2, 3}}
```

</details>

- `SortByDesc` calls a callback for each element and performs a descending sort by the return value of the callback

<details>
<summary>Examples</summary>

```go
collect.SortByDesc([]int{2, 1, 3}, func(item, index int) string {
return strconv.Itoa(item)
}) // *SliceCollection{[]int{3, 2, 1}}
```

</details>

## License

go-collection is [MIT licensed](LICENSE).
71 changes: 69 additions & 2 deletions README_zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ collect.Reduce(collect.Filter(collect.Map([]int{1, 2, 3}, fn), fn), fn)
collect.UseSlice([]int{1, 2, 3}).Map(fn).Filter(fn).Reduce(fn).All()
```

**_注意:由于 Go 1.18 还未正式发布,其语言行为仍可能在发布后产生变化,因此目前 go-collection 仅作试用用途。如果您有其它的疑问或建议,请[创建一个 issue](https://github.com/sxyazi/go-collection/issues/new)_**

**_注意:过去一周发布的 Go 1.18 Beta 2 仍存在一些 Bug,因此在试用 go-collection 时,您需要使用 [gotip](https://pkg.go.dev/golang.org/dl/gotip) 工具获取 Go 最新的 master 分支版本。_**

## 安装

```shell
Expand All @@ -28,7 +32,7 @@ import collect "github.com/sxyazi/go-collection"

## API

它的 API 非常简单,如果你用过其它类似的包,应该可以在几分钟内上手它。**为了方便,下面以函数的形式介绍它们**
它的 API 非常简单,如果您用过其它类似的包,应该可以在几分钟内上手它。**为了方便,下面以函数的形式介绍它们**

### 切片

Expand Down Expand Up @@ -334,6 +338,19 @@ import collect "github.com/sxyazi/go-collection"

</details>

- Reduce:将集合减少到一个单一的值,每轮迭代的参数为上一轮迭代的结果

<details>
<summary>例子</summary>

```go
collect.Reduce([]int{1, 2, 3}, 100, func(carry, value, key int) int {
return carry + value
}) // 106
```

</details>

- Count:统计切片中每个元素出现的次数

<details>
Expand All @@ -348,7 +365,7 @@ import collect "github.com/sxyazi/go-collection"

### 数组

[切片](#切片) 完全一致,你只需将数组转换为切片传入
[切片](#切片) 完全一致,您只需将数组转换为切片传入

```go
arr := [3]int{1, 2, 3}
Expand Down Expand Up @@ -532,6 +549,17 @@ collect.UseSlice(arr[:]).Len()

</details>

- SortDesc:对集合中的数字按降序排序

<details>
<summary>例子</summary>

```go
collect.SortDesc([]float64{1, -4, 0, -4.3}) // []float64{1, 0, -4, -4.3}
```

</details>

- Avg:求平均数

<details>
Expand Down Expand Up @@ -648,6 +676,45 @@ collect.UseSlice(arr[:]).Len()

</details>

- Times:通过调用指定次数的回调,创建一个新的切片集合

<details>
<summary>例子</summary>

```go
collect.Times(3, func(number int) float64 {
return float64(number) * 3.14
}) // *SliceCollection{[]float64{3.14, 6.28, 9.42}}
```

</details>

- SortBy:为每个元素调用回调函数,并按回调函数的返回值执行升序排序

<details>
<summary>例子</summary>

```go
collect.SortBy([]int{2, 1, 3}, func(item, index int) string {
return strconv.Itoa(item)
}) // *SliceCollection{[]int{1, 2, 3}}
```

</details>

- SortByDesc:为每个元素调用回调函数,并按回调函数的返回值执行降序排序

<details>
<summary>例子</summary>

```go
collect.SortByDesc([]int{2, 1, 3}, func(item, index int) string {
return strconv.Itoa(item)
}) // *SliceCollection{[]int{3, 2, 1}}
```

</details>

## 许可

go-collection is [MIT licensed](LICENSE).
19 changes: 16 additions & 3 deletions functional.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,12 @@ func Max[T ~[]E, E constraints.Integer | constraints.Float](items T) E {
}

func Sort[T ~[]E, E constraints.Ordered](items T) T {
sort.Sort(&types.SortableSlice[T, E]{items})
sort.Sort(&types.SortableSlice[T, E]{items, false})
return items
}

func SortDesc[T ~[]E, E constraints.Ordered](items T) T {
sort.Sort(&types.SortableSlice[T, E]{items, true})
return items
}

Expand Down Expand Up @@ -470,7 +475,7 @@ func Times[T ~[]E, E any](number int, callback func(number int) E) *SliceCollect
return UseSlice[T, E](items)
}

func SortBy[T ~[]E, E any, C func(item E, index int) R, R constraints.Ordered](items T, callback C) *SliceCollection[T, E] {
func sortBy[T ~[]E, E any, C func(item E, index int) R, R constraints.Ordered](items T, desc bool, callback C) *SliceCollection[T, E] {
structs := make([]*types.SortableStruct[R], len(items))
for index, item := range items {
structs[index] = &types.SortableStruct[R]{callback(item, index), index}
Expand All @@ -479,10 +484,18 @@ func SortBy[T ~[]E, E any, C func(item E, index int) R, R constraints.Ordered](i
replica := make(T, len(items))
copy(replica, items)

sort.Sort(&types.SortableStructs[[]R, R]{structs})
sort.Sort(&types.SortableStructs[[]R, R]{structs, desc})
for index, s := range structs {
items[index] = replica[s.Attached.(int)]
}

return UseSlice[T, E](items)
}

func SortBy[T ~[]E, E any, C func(item E, index int) R, R constraints.Ordered](items T, callback C) *SliceCollection[T, E] {
return sortBy[T, E, C, R](items, false, callback)
}

func SortByDesc[T ~[]E, E any, C func(item E, index int) R, R constraints.Ordered](items T, callback C) *SliceCollection[T, E] {
return sortBy[T, E, C, R](items, true, callback)
}
5 changes: 5 additions & 0 deletions number.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ func (n *NumberCollection[T, E]) Sort() *NumberCollection[T, E] {
return n
}

func (n *NumberCollection[T, E]) SortDesc() *NumberCollection[T, E] {
n.z = SortDesc[T, E](n.All())
return n
}

func (n *NumberCollection[T, E]) Avg() float64 {
return Avg[T, E](n.All())
}
Expand Down
8 changes: 8 additions & 0 deletions tests/functional_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,11 @@ func TestFunctional_SortBy(t *testing.T) {
t.Fail()
}
}

func TestFunctional_SortByDesc(t *testing.T) {
if !SortByDesc([]int{2, 1, 3}, func(item, index int) string {
return strconv.Itoa(item)
}).Same([]int{3, 2, 1}) {
t.Fail()
}
}
12 changes: 12 additions & 0 deletions tests/number_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ func TestNumber_Sort(t *testing.T) {
}
}

func TestNumber_SortDesc(t *testing.T) {
d1 := []float64{0, 17.5, -4.01, 0.2, 59, 33, -4}
if !UseNumber(d1).SortDesc().Same([]float64{59, 33, 17.5, 0.2, 0, -4, -4.01}) {
t.Fail()
}

d2 := []int{392, 17, 65, 0, 59, 33, -4}
if !UseNumber(d2).SortDesc().Same([]int{392, 65, 59, 33, 17, 0, -4}) {
t.Fail()
}
}

func TestNumber_Avg(t *testing.T) {
d := []float64{0, 1.1, 2.2, 3.3, 4.4, 5.5}
if UseNumber(d).Avg() != 2.75 {
Expand Down
14 changes: 12 additions & 2 deletions types/sortable.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,19 @@ import (

type SortableSlice[T ~[]E, E constraints.Ordered] struct {
Items T
Desc bool
}

func (s SortableSlice[T, E]) Len() int {
return len(s.Items)
}

func (s SortableSlice[T, E]) Less(i, j int) bool {
return s.Items[i] < s.Items[j] || (s.Items[i] != s.Items[i] && s.Items[j] == s.Items[j])
if s.Desc {
return s.Items[j] < s.Items[i] || (s.Items[j] != s.Items[j] && s.Items[i] == s.Items[i])
} else {
return s.Items[i] < s.Items[j] || (s.Items[i] != s.Items[i] && s.Items[j] == s.Items[j])
}
}

func (s SortableSlice[T, E]) Swap(i, j int) {
Expand All @@ -35,14 +40,19 @@ type SortableStruct[E constraints.Ordered] struct {

type SortableStructs[T ~[]E, E constraints.Ordered] struct {
Items []*SortableStruct[E]
Desc bool
}

func (s SortableStructs[T, E]) Len() int {
return len(s.Items)
}

func (s SortableStructs[T, E]) Less(i, j int) bool {
return s.Items[i].Value < s.Items[j].Value || (s.Items[i].Value != s.Items[i].Value && s.Items[j].Value == s.Items[j].Value)
if s.Desc {
return s.Items[j].Value < s.Items[i].Value || (s.Items[j].Value != s.Items[j].Value && s.Items[i].Value == s.Items[i].Value)
} else {
return s.Items[i].Value < s.Items[j].Value || (s.Items[i].Value != s.Items[i].Value && s.Items[j].Value == s.Items[j].Value)
}
}

func (s SortableStructs[T, E]) Swap(i, j int) {
Expand Down

0 comments on commit af5798f

Please sign in to comment.