Skip to content

Commit

Permalink
feat: Add FromAnySlice (#133)
Browse files Browse the repository at this point in the history
* feat: adding FromAnySlice helper
  • Loading branch information
samber committed May 10, 2022
1 parent c03bb1d commit e0853ca
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 68 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

@samber: I sometimes forget to update this file. Ping me on [Twitter](https://twitter.com/samuelberthe) or open an issue in case of error. We need to keep a clear changelog for easier lib upgrade.

## 1.21.0 (2022-05-10)

Adding:

- lo.ToAnySlice
- lo.FromAnySlice

## 1.20.0 (2022-05-02)

Adding:
Expand Down
37 changes: 27 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ Supported helpers for slices:
- Reject
- Count
- CountBy
- ToInterfaceSlice

Supported helpers for maps:

Expand Down Expand Up @@ -144,13 +143,18 @@ Supported search helpers:
- Sample
- Samples

Other functional programming helpers:
Conditional helpers:

- Ternary (1 line if/else statement)
- If / ElseIf / Else
- Switch / Case / Default

Type manipulation helpers:

- ToPtr
- ToSlicePtr
- ToAnySlice
- FromAnySlice
- Empty
- Coalesce

Expand Down Expand Up @@ -636,14 +640,6 @@ slice := lo.ReplaceAll(in, -1, 42)
// []int{0, 1, 0, 1, 2, 3, 0}
```

### ToAnySlice

Returns a slice with all elements mapped to any type
```go
elements := lo.ToAnySlice[int]([]int{1, 5, 1})
// []any{1, 5, 1}
```

### Keys

Creates an array of the map keys.
Expand Down Expand Up @@ -1336,6 +1332,27 @@ ptr := lo.ToSlicePtr[string]([]string{"hello", "world"})
// []*string{"hello", "world"}
```

### ToAnySlice

Returns a slice with all elements mapped to `any` type.

```go
elements := lo.ToAnySlice[int]([]int{1, 5, 1})
// []any{1, 5, 1}
```

### FromAnySlice

Returns an `any` slice with all elements mapped to a type. Returns false in case of type conversion failure.

```go
elements, ok := lo.FromAnySlice[string]([]any{"foobar", 42})
// []string{}, false

elements, ok := lo.FromAnySlice[string]([]any{"foobar", "42"})
// []string{"foobar", "42"}, true
```

### Empty

Returns an empty value.
Expand Down
6 changes: 1 addition & 5 deletions find.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,7 @@ func Sample[T any](collection []T) T {
func Samples[T any](collection []T, count int) []T {
size := len(collection)

// put values into a map, for faster deletion
cOpy := make([]T, 0, size)
for _, v := range collection {
cOpy = append(cOpy, v)
}
cOpy := append([]T{}, collection...)

results := []T{}

Expand Down
32 changes: 0 additions & 32 deletions pointers.go

This file was deleted.

9 changes: 0 additions & 9 deletions slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,12 +406,3 @@ func Replace[T comparable](collection []T, old T, new T, n int) []T {
func ReplaceAll[T comparable](collection []T, old T, new T) []T {
return Replace[T](collection, old, new, -1)
}

// ToAnySlice returns a slice with all elements mapped to any type
func ToAnySlice[T any](collection []T) []any {
result := make([]any, len(collection))
for i, item := range collection {
result[i] = item
}
return result
}
12 changes: 0 additions & 12 deletions slice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,15 +455,3 @@ func TestReplaceAll(t *testing.T) {
is.Equal([]int{42, 1, 42, 1, 2, 3, 42}, out1)
is.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out2)
}

func TestToAnySlice(t *testing.T) {
is := assert.New(t)

in1 := []int{0, 1, 2, 3}
in2 := []int{}
out1 := ToAnySlice(in1)
out2 := ToAnySlice(in2)

is.Equal([]any{0, 1, 2, 3}, out1)
is.Equal([]any{}, out2)
}
58 changes: 58 additions & 0 deletions type_manipulation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package lo

// ToPtr returns a pointer copy of value.
func ToPtr[T any](x T) *T {
return &x
}

// ToSlicePtr returns a slice of pointer copy of value.
func ToSlicePtr[T any](collection []T) []*T {
return Map(collection, func(x T, _ int) *T {
return &x
})
}

// ToAnySlice returns a slice with all elements mapped to `any` type
func ToAnySlice[T any](collection []T) []any {
result := make([]any, len(collection))
for i, item := range collection {
result[i] = item
}
return result
}

// FromAnySlice returns an `any` slice with all elements mapped to a type.
// Returns false in case of type conversion failure.
func FromAnySlice[T any](in []any) (out []T, ok bool) {
defer func() {
if r := recover(); r != nil {
out = []T{}
ok = false
}
}()

result := make([]T, len(in))
for i, item := range in {
result[i] = item.(T)
}
return result, true
}

// Empty returns an empty value.
func Empty[T any]() T {
var t T
return t
}

// Coalesce returns the first non-empty arguments. Arguments must be comparable.
func Coalesce[T comparable](v ...T) (result T, ok bool) {
for _, e := range v {
if e != result {
result = e
ok = true
return
}
}

return
}
40 changes: 40 additions & 0 deletions pointers_test.go → type_manipulation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,46 @@ func TestToSlicePtr(t *testing.T) {
is.Equal(result1, []*string{&str1, &str2})
}

func TestToAnySlice(t *testing.T) {
is := assert.New(t)

in1 := []int{0, 1, 2, 3}
in2 := []int{}
out1 := ToAnySlice(in1)
out2 := ToAnySlice(in2)

is.Equal([]any{0, 1, 2, 3}, out1)
is.Equal([]any{}, out2)
}

func TestFromAnySlice(t *testing.T) {
is := assert.New(t)

is.NotPanics(func() {
out1, ok1 := FromAnySlice[string]([]any{"foobar", 42})
out2, ok2 := FromAnySlice[string]([]any{"foobar", "42"})

is.Equal([]string{}, out1)
is.False(ok1)
is.Equal([]string{"foobar", "42"}, out2)
is.True(ok2)
})
}

func TestEmpty(t *testing.T) {
is := assert.New(t)

//nolint:unused
type test struct {
foobar string
}

is.Empty(Empty[string]())
is.Empty(Empty[int64]())
is.Empty(Empty[test]())
is.Empty(Empty[chan string]())
}

func TestCoalesce(t *testing.T) {
is := assert.New(t)

Expand Down

0 comments on commit e0853ca

Please sign in to comment.