Skip to content

Commit

Permalink
feat: adding Replace and ReplaceAll
Browse files Browse the repository at this point in the history
  • Loading branch information
samber committed Apr 30, 2022
1 parent ca59c95 commit d22a2a2
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
Adding:

- lo.RepeatBy
- lo.Substring
- lo.Subset
- lo.Replace
- lo.ReplaceAll

## 1.18.0 (2022-04-28)

Expand Down
70 changes: 68 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ odd := lo.Reject[int]([]int{1, 2, 3, 4}, func(x int, _ int) bool {
Counts the number of elements in the collection that compare equal to value.

```go
count := Count[int]([]int{1, 5, 1}, 1)
count := lo.Count[int]([]int{1, 5, 1}, 1)
// 2
```

Expand All @@ -572,12 +572,78 @@ count := Count[int]([]int{1, 5, 1}, 1)
Counts the number of elements in the collection for which predicate is true.

```go
count := CountBy[int]([]int{1, 5, 1}, func(i int) bool {
count := lo.CountBy[int]([]int{1, 5, 1}, func(i int) bool {
return i < 4
})
// 2
```

### Substring

Return part of a string.

```go
sub := lo.Substring("hello", 2, 3)
// "llo"

sub := lo.Substring("hello", -4, 3)
// "ell"

sub := lo.Substring("hello", -2, math.MaxUint)
// "lo"
```

### Subset

Return part of a slice.

```go
in := []int{0, 1, 2, 3, 4}

sub := lo.Subset(in, 2, 3)
// []int{2, 3, 4}

sub := lo.Subset(in, -4, 3)
// []int{1, 2, 3}

sub := lo.Subset(in, -2, math.MaxUint)
// []int{3, 4}
```

### Replace

Returns a copy of the slice with the first n non-overlapping instances of old replaced by new.

```go
in := []int{0, 1, 0, 1, 2, 3, 0}

slice := lo.Replace(in, 0, 42, 1)
// []int{42, 1, 0, 1, 2, 3, 0}

slice := lo.Replace(in, -1, 42, 1)
// []int{0, 1, 0, 1, 2, 3, 0}

slice := lo.Replace(in, 0, 42, 2)
// []int{42, 1, 42, 1, 2, 3, 0}

slice := lo.Replace(in, 0, 42, -1)
// []int{42, 1, 42, 1, 2, 3, 42}
```

### ReplaceAll

Returns a copy of the slice with all non-overlapping instances of old replaced by new.

```go
in := []int{0, 1, 0, 1, 2, 3, 0}

slice := lo.ReplaceAll(in, 0, 42)
// []int{42, 1, 42, 1, 2, 3, 42}

slice := lo.ReplaceAll(in, -1, 42)
// []int{0, 1, 0, 1, 2, 3, 0}
```

### Keys

Creates an array of the map keys.
Expand Down
66 changes: 66 additions & 0 deletions slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,3 +362,69 @@ func CountBy[T any](collection []T, predicate func(T) bool) (count int) {

return count
}

// Substring return part of a string.
func Substring[T ~string](str T, offset int, length uint) T {
size := len(str)

if offset < 0 {
offset = size + offset
if offset < 0 {
offset = 0
}
}

if offset > size {
return Empty[T]()
}

if length > uint(size)-uint(offset) {
length = uint(size - offset)
}

return str[offset : offset+int(length)]
}

// Subset return part of a slice.
func Subset[T any](collection []T, offset int, length uint) []T {
size := len(collection)

if offset < 0 {
offset = size + offset
if offset < 0 {
offset = 0
}
}

if offset > size {
return []T{}
}

if length > uint(size)-uint(offset) {
length = uint(size - offset)
}

return collection[offset : offset+int(length)]
}

// Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
func Replace[T comparable](collection []T, old T, new T, n int) []T {
size := len(collection)
result := make([]T, 0, size)

for _, item := range collection {
if item == old && n != 0 {
result = append(result, new)
n--
} else {
result = append(result, item)
}
}

return result
}

// ReplaceAll returns a copy of the slice with all non-overlapping instances of old replaced by new.
func ReplaceAll[T comparable](collection []T, old T, new T) []T {
return Replace[T](collection, old, new, -1)
}
102 changes: 102 additions & 0 deletions slice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,3 +383,105 @@ func TestCountBy(t *testing.T) {
is.Equal(count2, 0)
is.Equal(count3, 0)
}

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

str1 := Substring("hello", 0, 0)
str2 := Substring("hello", 10, 2)
str3 := Substring("hello", -10, 2)
str4 := Substring("hello", 0, 10)
str5 := Substring("hello", 0, 2)
str6 := Substring("hello", 2, 2)
str7 := Substring("hello", 2, 5)
str8 := Substring("hello", 2, 3)
str9 := Substring("hello", 2, 4)
str10 := Substring("hello", -2, 4)
str11 := Substring("hello", -4, 1)
str12 := Substring("hello", -4, math.MaxUint)

is.Equal("", str1)
is.Equal("", str2)
is.Equal("he", str3)
is.Equal("hello", str4)
is.Equal("he", str5)
is.Equal("ll", str6)
is.Equal("llo", str7)
is.Equal("llo", str8)
is.Equal("llo", str9)
is.Equal("lo", str10)
is.Equal("e", str11)
is.Equal("ello", str12)
}

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

in := []int{0, 1, 2, 3, 4}

out1 := Subset(in, 0, 0)
out2 := Subset(in, 10, 2)
out3 := Subset(in, -10, 2)
out4 := Subset(in, 0, 10)
out5 := Subset(in, 0, 2)
out6 := Subset(in, 2, 2)
out7 := Subset(in, 2, 5)
out8 := Subset(in, 2, 3)
out9 := Subset(in, 2, 4)
out10 := Subset(in, -2, 4)
out11 := Subset(in, -4, 1)
out12 := Subset(in, -4, math.MaxUint)

is.Equal([]int{}, out1)
is.Equal([]int{}, out2)
is.Equal([]int{0, 1}, out3)
is.Equal([]int{0, 1, 2, 3, 4}, out4)
is.Equal([]int{0, 1}, out5)
is.Equal([]int{2, 3}, out6)
is.Equal([]int{2, 3, 4}, out7)
is.Equal([]int{2, 3, 4}, out8)
is.Equal([]int{2, 3, 4}, out9)
is.Equal([]int{3, 4}, out10)
is.Equal([]int{1}, out11)
is.Equal([]int{1, 2, 3, 4}, out12)
}

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

in := []int{0, 1, 0, 1, 2, 3, 0}

out1 := Replace(in, 0, 42, 2)
out2 := Replace(in, 0, 42, 1)
out3 := Replace(in, 0, 42, 0)
out4 := Replace(in, 0, 42, -1)
out5 := Replace(in, 0, 42, -1)
out6 := Replace(in, -1, 42, 2)
out7 := Replace(in, -1, 42, 1)
out8 := Replace(in, -1, 42, 0)
out9 := Replace(in, -1, 42, -1)
out10 := Replace(in, -1, 42, -1)

is.Equal([]int{42, 1, 42, 1, 2, 3, 0}, out1)
is.Equal([]int{42, 1, 0, 1, 2, 3, 0}, out2)
is.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out3)
is.Equal([]int{42, 1, 42, 1, 2, 3, 42}, out4)
is.Equal([]int{42, 1, 42, 1, 2, 3, 42}, out5)
is.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out6)
is.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out7)
is.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out8)
is.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out9)
is.Equal([]int{0, 1, 0, 1, 2, 3, 0}, out10)
}

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

in := []int{0, 1, 0, 1, 2, 3, 0}

out1 := ReplaceAll(in, 0, 42)
out2 := ReplaceAll(in, -1, 42)

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

0 comments on commit d22a2a2

Please sign in to comment.