Move string slice functions to slice package as generic functions

This commit is contained in:
Deluan 2023-06-02 16:30:20 -04:00
parent c4c99b7f75
commit 3fc4313e89
5 changed files with 67 additions and 65 deletions

View File

@ -5,7 +5,7 @@ import (
"github.com/deluan/rest"
"github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/model"
"github.com/navidrome/navidrome/utils"
"github.com/navidrome/navidrome/utils/slice"
)
type playlistTrackRepository struct {
@ -196,7 +196,7 @@ func (r *playlistTrackRepository) Reorder(pos int, newPos int) error {
if err != nil {
return err
}
newOrder := utils.MoveString(ids, pos-1, newPos-1)
newOrder := slice.Move(ids, pos-1, newPos-1)
return r.playlistRepo.updatePlaylist(r.playlistId, newOrder)
}

View File

@ -41,3 +41,16 @@ func MostFrequent[T comparable](list []T) T {
return topItem
}
func Insert[T any](slice []T, value T, index int) []T {
return append(slice[:index], append([]T{value}, slice[index:]...)...)
}
func Remove[T any](slice []T, index int) []T {
return append(slice[:index], slice[index+1:]...)
}
func Move[T any](slice []T, srcIndex int, dstIndex int) []T {
value := slice[srcIndex]
return Insert(Remove(slice, srcIndex), value, dstIndex)
}

View File

@ -14,45 +14,59 @@ func TestSlice(t *testing.T) {
RunSpecs(t, "Slice Suite")
}
var _ = Describe("Map", func() {
It("returns empty slice for an empty input", func() {
mapFunc := func(v int) string { return strconv.Itoa(v * 2) }
result := slice.Map([]int{}, mapFunc)
Expect(result).To(BeEmpty())
var _ = Describe("Slice Utils", func() {
Describe("Map", func() {
It("returns empty slice for an empty input", func() {
mapFunc := func(v int) string { return strconv.Itoa(v * 2) }
result := slice.Map([]int{}, mapFunc)
Expect(result).To(BeEmpty())
})
It("returns a new slice with elements mapped", func() {
mapFunc := func(v int) string { return strconv.Itoa(v * 2) }
result := slice.Map([]int{1, 2, 3, 4}, mapFunc)
Expect(result).To(ConsistOf("2", "4", "6", "8"))
})
})
It("returns a new slice with elements mapped", func() {
mapFunc := func(v int) string { return strconv.Itoa(v * 2) }
result := slice.Map([]int{1, 2, 3, 4}, mapFunc)
Expect(result).To(ConsistOf("2", "4", "6", "8"))
})
})
var _ = Describe("Group", func() {
It("returns empty map for an empty input", func() {
keyFunc := func(v int) int { return v % 2 }
result := slice.Group([]int{}, keyFunc)
Expect(result).To(BeEmpty())
})
It("groups by the result of the key function", func() {
keyFunc := func(v int) int { return v % 2 }
result := slice.Group([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, keyFunc)
Expect(result).To(HaveLen(2))
Expect(result[0]).To(ConsistOf(2, 4, 6, 8, 10))
Expect(result[1]).To(ConsistOf(1, 3, 5, 7, 9, 11))
})
})
var _ = Describe("MostFrequent", func() {
It("returns zero value if no arguments are passed", func() {
Expect(slice.MostFrequent([]int{})).To(BeZero())
})
It("returns the single item", func() {
Expect(slice.MostFrequent([]string{"123"})).To(Equal("123"))
})
It("returns the item that appeared more times", func() {
Expect(slice.MostFrequent([]string{"1", "2", "1", "2", "3", "2"})).To(Equal("2"))
Describe("Group", func() {
It("returns empty map for an empty input", func() {
keyFunc := func(v int) int { return v % 2 }
result := slice.Group([]int{}, keyFunc)
Expect(result).To(BeEmpty())
})
It("groups by the result of the key function", func() {
keyFunc := func(v int) int { return v % 2 }
result := slice.Group([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, keyFunc)
Expect(result).To(HaveLen(2))
Expect(result[0]).To(ConsistOf(2, 4, 6, 8, 10))
Expect(result[1]).To(ConsistOf(1, 3, 5, 7, 9, 11))
})
})
Describe("MostFrequent", func() {
It("returns zero value if no arguments are passed", func() {
Expect(slice.MostFrequent([]int{})).To(BeZero())
})
It("returns the single item", func() {
Expect(slice.MostFrequent([]string{"123"})).To(Equal("123"))
})
It("returns the item that appeared more times", func() {
Expect(slice.MostFrequent([]string{"1", "2", "1", "2", "3", "2"})).To(Equal("2"))
})
})
Describe("Move", func() {
It("moves item to end of slice", func() {
Expect(slice.Move([]string{"1", "2", "3"}, 0, 2)).To(ConsistOf("2", "3", "1"))
})
It("moves item to beginning of slice", func() {
Expect(slice.Move([]string{"1", "2", "3"}, 2, 0)).To(ConsistOf("3", "1", "2"))
})
It("keeps item in same position if srcIndex == dstIndex", func() {
Expect(slice.Move([]string{"1", "2", "3"}, 1, 1)).To(ConsistOf("1", "2", "3"))
})
})
})

View File

@ -17,19 +17,6 @@ func NoArticle(name string) string {
return name
}
func InsertString(slice []string, value string, index int) []string {
return append(slice[:index], append([]string{value}, slice[index:]...)...)
}
func RemoveString(slice []string, index int) []string {
return append(slice[:index], slice[index+1:]...)
}
func MoveString(slice []string, srcIndex int, dstIndex int) []string {
value := slice[srcIndex]
return InsertString(RemoveString(slice, srcIndex), value, dstIndex)
}
func BreakUpStringSlice(items []string, chunkSize int) [][]string {
numTracks := len(items)
var chunks [][]string

View File

@ -35,18 +35,6 @@ var _ = Describe("Strings", func() {
})
})
Describe("MoveString", func() {
It("moves item to end of slice", func() {
Expect(MoveString([]string{"1", "2", "3"}, 0, 2)).To(ConsistOf("2", "3", "1"))
})
It("moves item to beginning of slice", func() {
Expect(MoveString([]string{"1", "2", "3"}, 2, 0)).To(ConsistOf("3", "1", "2"))
})
It("keeps item in same position if srcIndex == dstIndex", func() {
Expect(MoveString([]string{"1", "2", "3"}, 1, 1)).To(ConsistOf("1", "2", "3"))
})
})
Describe("BreakUpStringSlice", func() {
It("returns no chunks if slice is empty", func() {
var slice []string