Skip to content

Commit

Permalink
add Interleave helper to slices (#155)
Browse files Browse the repository at this point in the history
* initial interleave working

* add nil case

* Update README.md

Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
  • Loading branch information
dillonstreator and samber committed Oct 10, 2022
1 parent ce01c4c commit fd5527f
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 0 deletions.
10 changes: 10 additions & 0 deletions README.md
Expand Up @@ -73,6 +73,7 @@ Supported helpers for slices:
- [Chunk](#chunk)
- [PartitionBy](#partitionby)
- [Flatten](#flatten)
- [Interleave](#interleave)
- [Shuffle](#shuffle)
- [Reverse](#reverse)
- [Fill](#fill)
Expand Down Expand Up @@ -499,6 +500,15 @@ flat := lo.Flatten[int]([][]int{{0, 1}, {2, 3, 4, 5}})

[[play](https://go.dev/play/p/rbp9ORaMpjw)]

### Interleave

Round-robbin alternating input slices and sequentially appending value at index into result.

```go
interleaved := lo.Interleave[int]([]int{1, 4, 7}, []int{2, 5, 8}, []int{3, 6, 9})
// []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
```

### Shuffle

Returns an array of shuffled values. Uses the Fisher-Yates shuffle algorithm.
Expand Down
37 changes: 37 additions & 0 deletions slice.go
Expand Up @@ -546,3 +546,40 @@ func IsSortedByKey[T any, K constraints.Ordered](collection []T, iteratee func(T

return true
}

// Interleave round-robbin alternating input slices and sequentially appending value at index into result
func Interleave[T any](collections ...[]T) []T {
if len(collections) == 0 {
return []T{}
}

maxSize := 0
totalSize := 0
for _, c := range collections {
size := len(c)
totalSize += size
if size > maxSize {
maxSize = size
}
}

if maxSize == 0 {
return []T{}
}

result := make([]T, totalSize)

resultIdx := 0
for i := 0; i < maxSize; i++ {
for j := range collections {
if len(collections[j])-1 < i {
continue
}

result[resultIdx] = collections[j][i]
resultIdx++
}
}

return result
}
47 changes: 47 additions & 0 deletions slice_test.go
Expand Up @@ -3,6 +3,7 @@ package lo
import (
"fmt"
"math"
"reflect"
"strconv"
"strings"
"testing"
Expand Down Expand Up @@ -666,3 +667,49 @@ func TestIsSortedByKey(t *testing.T) {
return ret
}))
}

func TestInterleave(t *testing.T) {
tests := []struct {
name string
collections [][]int
want []int
}{
{
"nil",
[][]int{nil},
[]int{},
},
{
"empty",
[][]int{},
[]int{},
},
{
"empties",
[][]int{{}, {}},
[]int{},
},
{
"same length",
[][]int{{1, 3, 5}, {2, 4, 6}},
[]int{1, 2, 3, 4, 5, 6},
},
{
"different length",
[][]int{{1, 3, 5, 6}, {2, 4}},
[]int{1, 2, 3, 4, 5, 6},
},
{
"many slices",
[][]int{{1}, {2, 5, 8}, {3, 6}, {4, 7, 9, 10}},
[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Interleave(tt.collections...); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Interleave() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit fd5527f

Please sign in to comment.