Repository: elliotchance/pie
Pull request #51 (2019-04-12 00:51:04)

Added ToStrings()
ToStrings transforms each element to a string.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/elliotchance/pie/51)
<!-- Reviewable:end -->



Patch:
diff --git a/README.md b/README.md
index 75ba173..0615081 100644
--- a/README.md
+++ b/README.md
@@ -136,6 +136,7 @@ This will only generate `myInts.Average`, `myInts.Sum` and `myStrings.Select`.
 | `Select`     | ✓      | ✓      | ✓      | n        | A new slice containing only the elements that returned true from the condition. |
 | `Sort`       | ✓      | ✓      |        | n⋅log(n) | Return a new sorted slice. |
 | `Sum`        |        | ✓      |        | n        | Sum (total) of all elements. |
+| `ToStrings`  | ✓      | ✓      | ✓      | n        | Transforms each element to a string. |
 | `Transform`  | ✓      | ✓      | ✓      | n        | A new slice where each element has been transformed. |
 | `Unique`     | ✓      | ✓      |        | n⋅log(n) | Return a new slice with only unique elements. |
 | `Unselect`   | ✓      | ✓      | ✓      | n        | A new slice containing only the elements that returned false from the condition. |
diff --git a/main.go b/main.go
index dc321c9..44edc47 100644
--- a/main.go
+++ b/main.go
@@ -78,7 +78,7 @@ func getType(name string) string {
 	return "struct"
 }
 
-func getImports(s string) (imports []string) {
+func getImports(packageName, s string) (imports []string) {
 	fset := token.NewFileSet()
 	f, err := parser.ParseFile(fset, "", s, parser.ImportsOnly)
 	if err != nil {
@@ -86,17 +86,24 @@ func getImports(s string) (imports []string) {
 	}
 
 	for _, s := range f.Imports {
-		imports = append(imports, s.Path.Value)
+		importName := s.Path.Value
+
+		if importName == `"github.com/elliotchance/pie/pie"` &&
+			isSelfPackage(packageName) {
+			continue
+		}
+
+		imports = append(imports, importName)
 	}
 
 	return
 }
 
-func getAllImports(files []string) (imports []string) {
+func getAllImports(packageName string, files []string) (imports []string) {
 	mapImports := map[string]struct{}{}
 
 	for _, file := range files {
-		for _, imp := range getImports(file) {
+		for _, imp := range getImports(packageName, file) {
 			mapImports[imp] = struct{}{}
 		}
 	}
@@ -110,6 +117,12 @@ func getAllImports(files []string) (imports []string) {
 	return
 }
 
+// We have to generate imports slightly differently when we are building code
+// that will go into its own packages vs an external package.
+func isSelfPackage(packageName string) bool {
+	return packageName == "pie"
+}
+
 func main() {
 	fset := token.NewFileSet()
 	pkgs, err := parser.ParseDir(fset, ".", nil, 0)
@@ -133,7 +146,7 @@ func main() {
 
 		// Aggregate imports.
 		t := fmt.Sprintf("package %s\n\nimport (", packageName)
-		for _, imp := range getAllImports(templates) {
+		for _, imp := range getAllImports(packageName, templates) {
 			t += fmt.Sprintf("\n\t%s", imp)
 		}
 		t += "\n)\n\n"
@@ -165,6 +178,10 @@ func main() {
 			t = strings.Replace(t, "ElementZeroValue", zeroValue, -1)
 		}
 
+		if isSelfPackage(packageName) {
+			t = strings.Replace(t, "pie.Strings", "Strings", -1)
+		}
+
 		// The TrimRight is important to remove an extra new line that conflicts
 		// with go fmt.
 		t = strings.TrimRight(t, "\n") + "\n"
diff --git a/pie/carpointers_pie.go b/pie/carpointers_pie.go
index f813aa1..e3a15ba 100755
--- a/pie/carpointers_pie.go
+++ b/pie/carpointers_pie.go
@@ -98,3 +98,18 @@ func (ss carPointers) Reverse() carPointers {
 
 	return sorted
 }
+
+func (ss carPointers) ToStrings(transform func(*car) string) Strings {
+	l := len(ss)
+
+	if l == 0 {
+		return nil
+	}
+
+	result := make(Strings, l)
+	for i := 0; i < l; i++ {
+		result[i] = transform(ss[i])
+	}
+
+	return result
+}
diff --git a/pie/cars_pie.go b/pie/cars_pie.go
index 018afb9..72478f0 100755
--- a/pie/cars_pie.go
+++ b/pie/cars_pie.go
@@ -98,3 +98,18 @@ func (ss cars) Reverse() cars {
 
 	return sorted
 }
+
+func (ss cars) ToStrings(transform func(car) string) Strings {
+	l := len(ss)
+
+	if l == 0 {
+		return nil
+	}
+
+	result := make(Strings, l)
+	for i := 0; i < l; i++ {
+		result[i] = transform(ss[i])
+	}
+
+	return result
+}
diff --git a/pie/float64s_pie.go b/pie/float64s_pie.go
index c7f7261..d78fdbf 100755
--- a/pie/float64s_pie.go
+++ b/pie/float64s_pie.go
@@ -100,6 +100,21 @@ func (ss Float64s) Reverse() Float64s {
 	return sorted
 }
 
+func (ss Float64s) ToStrings(transform func(float64) string) Strings {
+	l := len(ss)
+
+	if l == 0 {
+		return nil
+	}
+
+	result := make(Strings, l)
+	for i := 0; i < l; i++ {
+		result[i] = transform(ss[i])
+	}
+
+	return result
+}
+
 func (ss Float64s) AreSorted() bool {
 	return sort.SliceIsSorted(ss, func(i, j int) bool {
 		return ss[i] < ss[j]
diff --git a/pie/ints_pie.go b/pie/ints_pie.go
index 6a4db4f..998187d 100755
--- a/pie/ints_pie.go
+++ b/pie/ints_pie.go
@@ -100,6 +100,21 @@ func (ss Ints) Reverse() Ints {
 	return sorted
 }
 
+func (ss Ints) ToStrings(transform func(int) string) Strings {
+	l := len(ss)
+
+	if l == 0 {
+		return nil
+	}
+
+	result := make(Strings, l)
+	for i := 0; i < l; i++ {
+		result[i] = transform(ss[i])
+	}
+
+	return result
+}
+
 func (ss Ints) AreSorted() bool {
 	return sort.SliceIsSorted(ss, func(i, j int) bool {
 		return ss[i] < ss[j]
diff --git a/pie/strings_pie.go b/pie/strings_pie.go
index 9f6065d..4b90ccc 100755
--- a/pie/strings_pie.go
+++ b/pie/strings_pie.go
@@ -100,6 +100,21 @@ func (ss Strings) Reverse() Strings {
 	return sorted
 }
 
+func (ss Strings) ToStrings(transform func(string) string) Strings {
+	l := len(ss)
+
+	if l == 0 {
+		return nil
+	}
+
+	result := make(Strings, l)
+	for i := 0; i < l; i++ {
+		result[i] = transform(ss[i])
+	}
+
+	return result
+}
+
 func (ss Strings) AreSorted() bool {
 	return sort.SliceIsSorted(ss, func(i, j int) bool {
 		return ss[i] < ss[j]
diff --git a/pie_all.go b/pie_all.go
index 015586e..ed5c677 100644
--- a/pie_all.go
+++ b/pie_all.go
@@ -2,6 +2,7 @@ package main
 
 import (
 	"encoding/json"
+	"github.com/elliotchance/pie/pie"
 )
 
 // The functions in this file work for all slices types.
@@ -133,3 +134,20 @@ func (ss SliceType) Reverse() SliceType {
 
 	return sorted
 }
+
+// ToStrings transforms each element to a string.
+func (ss SliceType) ToStrings(transform func(ElementType) string) pie.Strings {
+	l := len(ss)
+
+	// Avoid the allocation.
+	if l == 0 {
+		return nil
+	}
+
+	result := make(pie.Strings, l)
+	for i := 0; i < l; i++ {
+		result[i] = transform(ss[i])
+	}
+
+	return result
+}
diff --git a/template.go b/template.go
index 5f06e31..0a50327 100644
--- a/template.go
+++ b/template.go
@@ -5,6 +5,7 @@ var pieAllTemplate = `package main
 
 import (
 	"encoding/json"
+	"github.com/elliotchance/pie/pie"
 )
 
 // The functions in this file work for all slices types.
@@ -136,6 +137,23 @@ func (ss SliceType) Reverse() SliceType {
 
 	return sorted
 }
+
+// ToStrings transforms each element to a string.
+func (ss SliceType) ToStrings(transform func(ElementType) string) pie.Strings {
+	l := len(ss)
+
+	// Avoid the allocation.
+	if l == 0 {
+		return nil
+	}
+
+	result := make(pie.Strings, l)
+	for i := 0; i < l; i++ {
+		result[i] = transform(ss[i])
+	}
+
+	return result
+}
 `
 
 var pieStringsNumbersTemplate = `package main


Test patch:
diff --git a/pie/carpointers_test.go b/pie/carpointers_test.go
index 6ce981d..40b026d 100644
--- a/pie/carpointers_test.go
+++ b/pie/carpointers_test.go
@@ -1,6 +1,7 @@
 package pie
 
 import (
+	"fmt"
 	"github.com/stretchr/testify/assert"
 	"strings"
 	"testing"
@@ -293,3 +294,40 @@ func TestCarPointers_Reverse(t *testing.T) {
 		})
 	}
 }
+
+var stringsToStringsTests = []struct {
+	ss        carPointers
+	transform func(*car) string
+	expected  Strings
+}{
+	{
+		nil,
+		func(s *car) string {
+			return "foo"
+		},
+		nil,
+	},
+	{
+		carPointers{},
+		func(s *car) string {
+			return fmt.Sprintf("%s!", s.Name)
+		},
+		nil,
+	},
+	{
+		carPointers{&car{"bar", "yellow"}, &car{"Baz", "black"}, &car{"foo", "red"}},
+		func(s *car) string {
+			return fmt.Sprintf("%s!", s.Color)
+		},
+		Strings{"yellow!", "black!", "red!"},
+	},
+}
+
+func TestCarPointers_ToStrings(t *testing.T) {
+	for _, test := range stringsToStringsTests {
+		t.Run("", func(t *testing.T) {
+			defer assertImmutableCarPointers(t, &test.ss)()
+			assert.Equal(t, test.expected, test.ss.ToStrings(test.transform))
+		})
+	}
+}
diff --git a/pie/cars_test.go b/pie/cars_test.go
index 4b0ad42..f4762a7 100644
--- a/pie/cars_test.go
+++ b/pie/cars_test.go
@@ -1,6 +1,7 @@
 package pie
 
 import (
+	"fmt"
 	"github.com/stretchr/testify/assert"
 	"strings"
 	"testing"
@@ -283,3 +284,40 @@ func TestCars_Reverse(t *testing.T) {
 		})
 	}
 }
+
+var carsToStringsTests = []struct {
+	ss        cars
+	transform func(car) string
+	expected  Strings
+}{
+	{
+		nil,
+		func(s car) string {
+			return "foo"
+		},
+		nil,
+	},
+	{
+		cars{},
+		func(s car) string {
+			return fmt.Sprintf("%s!", s.Name)
+		},
+		nil,
+	},
+	{
+		cars{car{"bar", "yellow"}, car{"Baz", "black"}, car{"foo", "red"}},
+		func(s car) string {
+			return fmt.Sprintf("%s!", s.Color)
+		},
+		Strings{"yellow!", "black!", "red!"},
+	},
+}
+
+func TestCars_ToStrings(t *testing.T) {
+	for _, test := range carsToStringsTests {
+		t.Run("", func(t *testing.T) {
+			defer assertImmutableCars(t, &test.ss)()
+			assert.Equal(t, test.expected, test.ss.ToStrings(test.transform))
+		})
+	}
+}
diff --git a/pie/float64s_test.go b/pie/float64s_test.go
index 468fcaa..fc48306 100644
--- a/pie/float64s_test.go
+++ b/pie/float64s_test.go
@@ -1,6 +1,7 @@
 package pie
 
 import (
+	"fmt"
 	"github.com/stretchr/testify/assert"
 	"testing"
 )
@@ -395,3 +396,40 @@ func TestFloat64s_AreUnique(t *testing.T) {
 		})
 	}
 }
+
+var float64sToStringsTests = []struct {
+	ss        Float64s
+	transform func(float64) string
+	expected  Strings
+}{
+	{
+		nil,
+		func(s float64) string {
+			return "foo"
+		},
+		nil,
+	},
+	{
+		Float64s{},
+		func(s float64) string {
+			return fmt.Sprintf("%f!", s)
+		},
+		nil,
+	},
+	{
+		Float64s{6.2, 7.2, 8.2},
+		func(s float64) string {
+			return fmt.Sprintf("%.2f!", s)
+		},
+		Strings{"6.20!", "7.20!", "8.20!"},
+	},
+}
+
+func TestFloat64s_ToStrings(t *testing.T) {
+	for _, test := range float64sToStringsTests {
+		t.Run("", func(t *testing.T) {
+			defer assertImmutableFloat64s(t, &test.ss)()
+			assert.Equal(t, test.expected, test.ss.ToStrings(test.transform))
+		})
+	}
+}
diff --git a/pie/ints_test.go b/pie/ints_test.go
index 6ac65e4..3ab3549 100644
--- a/pie/ints_test.go
+++ b/pie/ints_test.go
@@ -1,6 +1,7 @@
 package pie
 
 import (
+	"fmt"
 	"github.com/stretchr/testify/assert"
 	"testing"
 )
@@ -381,3 +382,40 @@ func TestInts_AreUnique(t *testing.T) {
 		})
 	}
 }
+
+var intsToStringsTests = []struct {
+	ss        Ints
+	transform func(int) string
+	expected  Strings
+}{
+	{
+		nil,
+		func(s int) string {
+			return "foo"
+		},
+		nil,
+	},
+	{
+		Ints{},
+		func(s int) string {
+			return fmt.Sprintf("%d!", s)
+		},
+		nil,
+	},
+	{
+		Ints{6, 7, 8},
+		func(s int) string {
+			return fmt.Sprintf("%d!", s)
+		},
+		Strings{"6!", "7!", "8!"},
+	},
+}
+
+func TestInts_ToStrings(t *testing.T) {
+	for _, test := range intsToStringsTests {
+		t.Run("", func(t *testing.T) {
+			defer assertImmutableInts(t, &test.ss)()
+			assert.Equal(t, test.expected, test.ss.ToStrings(test.transform))
+		})
+	}
+}
diff --git a/pie/strings_test.go b/pie/strings_test.go
index 07627a3..0377fb6 100644
--- a/pie/strings_test.go
+++ b/pie/strings_test.go
@@ -1,6 +1,7 @@
 package pie
 
 import (
+	"fmt"
 	"github.com/stretchr/testify/assert"
 	"strings"
 	"testing"
@@ -368,3 +369,40 @@ func TestStrings_AreUnique(t *testing.T) {
 		})
 	}
 }
+
+var carPointersToStringsTests = []struct {
+	ss        Strings
+	transform func(string) string
+	expected  Strings
+}{
+	{
+		nil,
+		func(s string) string {
+			return "foo"
+		},
+		nil,
+	},
+	{
+		Strings{},
+		func(s string) string {
+			return fmt.Sprintf("%s!", s)
+		},
+		nil,
+	},
+	{
+		Strings{"6.2", "7.2", "8.2"},
+		func(s string) string {
+			return fmt.Sprintf("%s!", s)
+		},
+		Strings{"6.2!", "7.2!", "8.2!"},
+	},
+}
+
+func TestStrings_ToStrings(t *testing.T) {
+	for _, test := range carPointersToStringsTests {
+		t.Run("", func(t *testing.T) {
+			defer assertImmutableStrings(t, &test.ss)()
+			assert.Equal(t, test.expected, test.ss.ToStrings(test.transform))
+		})
+	}
+}