Repository: elliotchance/pie
Pull request #89 (2019-05-03 21:50:36)

Renames
Hey Elliot,

I've done the renames that we discussed in #86 
I altered the unit tests to reflect the changes in the names. All unit tests passed when I ran them, so I'm thinking this should work :) 

~ Dylan

<!-- 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/89)
<!-- Reviewable:end -->


codecov-io: # [Codecov](https://codecov.io/gh/elliotchance/pie/pull/89?src=pr&el=h1) Report
> :exclamation: No coverage uploaded for pull request base (`master@d220040`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference#section-missing-base-commit).
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/elliotchance/pie/pull/89/graphs/tree.svg?width=650&token=OvugwUQGM3&height=150&src=pr)](https://codecov.io/gh/elliotchance/pie/pull/89?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##             master    #89   +/-   ##
=======================================
  Coverage          ?   100%           
=======================================
  Files             ?      7           
  Lines             ?    743           
  Branches          ?      0           
=======================================
  Hits              ?    743           
  Misses            ?      0           
  Partials          ?      0
```


| [Impacted Files](https://codecov.io/gh/elliotchance/pie/pull/89?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pie/float64s\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/89/diff?src=pr&el=tree#diff-cGllL2Zsb2F0NjRzX3BpZS5nbw==) | `100% <100%> (ø)` | |
| [pie/carpointers\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/89/diff?src=pr&el=tree#diff-cGllL2NhcnBvaW50ZXJzX3BpZS5nbw==) | `100% <100%> (ø)` | |
| [pie/cars\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/89/diff?src=pr&el=tree#diff-cGllL2NhcnNfcGllLmdv) | `100% <100%> (ø)` | |
| [pie/strings\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/89/diff?src=pr&el=tree#diff-cGllL3N0cmluZ3NfcGllLmdv) | `100% <100%> (ø)` | |
| [pie/ints\_pie.go](https://codecov.io/gh/elliotchance/pie/pull/89/diff?src=pr&el=tree#diff-cGllL2ludHNfcGllLmdv) | `100% <100%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/elliotchance/pie/pull/89?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/elliotchance/pie/pull/89?src=pr&el=footer). Last update [d220040...4f7519a](https://codecov.io/gh/elliotchance/pie/pull/89?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

DylanMeeus: Woops sorry, 
I have just pushed the requested changes :) 
DylanMeeus: Looks like it has no conflicts now :) 

Patch:
diff --git a/README.md b/README.md
index 584755a..e76dcbe 100644
--- a/README.md
+++ b/README.md
@@ -48,10 +48,10 @@ import (
 
 func main() {
     name := pie.Strings{"Bob", "Sally", "John", "Jane"}.
-        Unselect(func (name string) bool {
+        FilterNot(func (name string) bool {
             return strings.HasPrefix(name, "J")
         }).
-        Transform(strings.ToUpper).
+        Map(strings.ToUpper).
         Last()
 
     fmt.Println(name) // "SALLY"
@@ -85,7 +85,7 @@ cars := Cars{
     {"Jane", "red"},
 }
 
-redCars := cars.Select(func(car Car) bool {
+redCars := cars.Filter(func(car Car) bool {
     return car.Color == "red"
 })
 
@@ -95,10 +95,10 @@ redCars := cars.Select(func(car Car) bool {
 Or, more complex operations can be chained:
 
 ```go
-cars.Unselect(func (car Car) {
+cars.FilterNot(func (car Car) {
         return strings.HasPrefix(car.Name, "J")
     }).
-    Transform(func (car Car) Car {
+    Map(func (car Car) Car {
         car.Name = strings.ToUpper(car.Name)
 
         return car
@@ -115,10 +115,10 @@ creates a lot of unused code. You can limit the functions generated by chaining
 the function names with a dot syntax, like:
 
 ```go
-//go:generate myInts.Average.Sum myStrings.Select
+//go:generate myInts.Average.Sum myStrings.Filter
 ```
 
-This will only generate `myInts.Average`, `myInts.Sum` and `myStrings.Select`.
+This will only generate `myInts.Average`, `myInts.Sum` and `myStrings.Filter`.
 
 # Functions
 
@@ -135,6 +135,8 @@ This will only generate `myInts.Average`, `myInts.Sum` and `myStrings.Select`.
 | `Contains`   | ✓      | ✓      | ✓     |      | n        | Check if the value exists in the slice. |
 | `Extend`     | ✓      | ✓      | ✓     |      | n        | A new slice with the elements from each slice appended to the end. |
 | `Each`       | ✓      | ✓      | ✓     |      | n        | Perform an action on each element. |
+| `Filter`     | ✓      | ✓      | ✓     |      | n        | A new slice containing only the elements that returned true from the condition. |
+| `FilterNot`  | ✓      | ✓      | ✓     |      | n        | A new slice containing only the elements that returned false from the condition. |
 | `First`      | ✓      | ✓      | ✓     |      | 1        | The first element, or a zeroed value. |
 | `FirstOr`    | ✓      | ✓      | ✓     |      | 1        | The first element, or a default value. |
 | `Join`       | ✓      |        |       |      | n        | A string from joining each of the elements. |
@@ -143,21 +145,19 @@ This will only generate `myInts.Average`, `myInts.Sum` and `myStrings.Select`.
 | `Last`       | ✓      | ✓      | ✓     |      | 1        | The last element, or a zeroed value. |
 | `LastOr`     | ✓      | ✓      | ✓     |      | 1        | The last element, or a default value. |
 | `Len`        | ✓      | ✓      | ✓     |      | 1        | Number of elements. |
+| `Map`	       | ✓      | ✓      | ✓     |      | n        | A new slice where each element has been mapped (transformed). |
 | `Max`        | ✓      | ✓      |       |      | n        | The maximum value, or a zeroes value. |
 | `Median`     |        | ✓      |       |      | n⋅log(n) | Median returns the value separating the higher half from the lower half of a data sample. |
 | `Min`        | ✓      | ✓      |       |      | n        | The minimum value, or a zeroed value. |
 | `Random`     | ✓      | ✓      | ✓     |      | 1        | Select a random element, or a zeroed value if empty. |
 | `Reverse`    | ✓      | ✓      | ✓     |      | n        | Reverse elements. |
 | `Send`     | ✓      | ✓      | ✓     |      | n        | Send all element to channel. |
-| `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. |
 | `Shuffle`    | ✓      | ✓      | ✓     |      | n        | Returns a new shuffled slice. |
 | `Top`        | ✓      | ✓      | ✓     |      | n        | Gets several elements from top(head of slice).|
 | `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. |
 | `Values`     |        |        |       | ✓    | n        | Returns all values in the map (in random order). |
 
 # FAQ
diff --git a/functions/select.go b/functions/filter.go
similarity index 54%
rename from functions/select.go
rename to functions/filter.go
index f539264..1fa7074 100644
--- a/functions/select.go
+++ b/functions/filter.go
@@ -1,15 +1,14 @@
 package functions
 
-// Select will return a new slice containing only the elements that return
+// Filter will return a new slice containing only the elements that return
 // true from the condition. The returned slice may contain zero elements (nil).
 //
-// Unselect works in the opposite way as Select.
-func (ss SliceType) Select(condition func(ElementType) bool) (ss2 SliceType) {
+// FilterNot works in the opposite way of Filter.
+func (ss SliceType) Filter(condition func(ElementType) bool) (ss2 SliceType) {
 	for _, s := range ss {
 		if condition(s) {
 			ss2 = append(ss2, s)
 		}
 	}
-
 	return
 }
diff --git a/functions/unselect.go b/functions/filter_not.go
similarity index 60%
rename from functions/unselect.go
rename to functions/filter_not.go
index 6c6f8c3..4302643 100644
--- a/functions/unselect.go
+++ b/functions/filter_not.go
@@ -1,9 +1,9 @@
 package functions
 
-// Unselect works the same as Select, with a negated condition. That is, it will
+// FilterNot works the same as Filter, with a negated condition. That is, it will
 // return a new slice only containing the elements that returned false from the
 // condition. The returned slice may contain zero elements (nil).
-func (ss SliceType) Unselect(condition func(ElementType) bool) (ss2 SliceType) {
+func (ss SliceType) FilterNot(condition func(ElementType) bool) (ss2 SliceType) {
 	for _, s := range ss {
 		if !condition(s) {
 			ss2 = append(ss2, s)
diff --git a/functions/main.go b/functions/main.go
index 234aa20..c9ed4bf 100644
--- a/functions/main.go
+++ b/functions/main.go
@@ -29,6 +29,8 @@ var Functions = []struct {
 	{"Contains", "contains.go", ForAll},
 	{"Each", "each.go", ForAll},
 	{"Extend", "extend.go", ForAll},
+	{"Filter", "filter.go", ForAll},
+	{"FilterNot", "filter_not.go", ForAll},
 	{"First", "first.go", ForAll},
 	{"FirstOr", "first_or.go", ForAll},
 	{"Join", "join.go", ForStrings},
@@ -37,21 +39,19 @@ var Functions = []struct {
 	{"Last", "last.go", ForAll},
 	{"LastOr", "last_or.go", ForAll},
 	{"Len", "len.go", ForAll},
+	{"Map", "map.go", ForAll},
 	{"Max", "max.go", ForNumbersAndStrings},
 	{"Median", "median.go", ForNumbers},
 	{"Min", "min.go", ForNumbersAndStrings},
 	{"Random", "random.go", ForAll},
 	{"Reverse", "reverse.go", ForAll},
 	{"Send", "send.go", ForAll},
-	{"Select", "select.go", ForAll},
 	{"Sort", "sort.go", ForNumbersAndStrings},
 	{"Sum", "sum.go", ForNumbers},
 	{"Shuffle", "shuffle.go", ForAll},
 	{"Top", "top.go", ForAll},
 	{"ToStrings", "to_strings.go", ForAll},
-	{"Transform", "transform.go", ForAll},
 	{"Unique", "unique.go", ForNumbersAndStrings},
-	{"Unselect", "unselect.go", ForAll},
 	{"Values", "values.go", ForMaps},
 }
 
diff --git a/functions/transform.go b/functions/map.go
similarity index 59%
rename from functions/transform.go
rename to functions/map.go
index a366bf6..6de20cd 100644
--- a/functions/transform.go
+++ b/functions/map.go
@@ -1,12 +1,12 @@
 package functions
 
-// Transform will return a new slice where each element has been transformed.
-// The number of element returned will always be the same as the input.
+// Map will return a new slice where each element has been mapped (transformed).
+// The number of elements returned will always be the same as the input.
 //
 // Be careful when using this with slices of pointers. If you modify the input
 // value it will affect the original slice. Be sure to return a new allocated
 // object or deep copy the existing one.
-func (ss SliceType) Transform(fn func(ElementType) ElementType) (ss2 SliceType) {
+func (ss SliceType) Map(fn func(ElementType) ElementType) (ss2 SliceType) {
 	if ss == nil {
 		return nil
 	}
diff --git a/main.go b/main.go
index de4b553..9adae96 100644
--- a/main.go
+++ b/main.go
@@ -5,7 +5,6 @@ package main
 import (
 	"fmt"
 	"github.com/elliotchance/pie/functions"
-	"github.com/elliotchance/pie/pie"
 	"go/ast"
 	"go/parser"
 	"go/token"
@@ -141,7 +140,7 @@ func main() {
 
 		var templates []string
 		for _, function := range functions.Functions {
-			if fns[0] != "*" && !pie.Strings(fns).Contains(function.Name) {
+			if fns[0] != "*" && !stringSliceContains(fns, function.Name) {
 				continue
 			}
 
@@ -216,3 +215,16 @@ func getFunctionsFromArg(arg string) (mapOrSliceType string, fns []string) {
 
 	return parts[0], parts[1:]
 }
+
+func stringSliceContains(haystack []string, needle string) bool {
+	if haystack == nil {
+		return false
+	}
+
+	for _, w := range haystack {
+		if w == needle {
+			return true
+		}
+	}
+	return false
+}
diff --git a/pie/carpointers_pie.go b/pie/carpointers_pie.go
index 17d5222..617163d 100755
--- a/pie/carpointers_pie.go
+++ b/pie/carpointers_pie.go
@@ -110,6 +110,32 @@ func (ss carPointers) Extend(slices ...carPointers) (ss2 carPointers) {
 	return ss2
 }
 
+// Filter will return a new slice containing only the elements that return
+// true from the condition. The returned slice may contain zero elements (nil).
+//
+// FilterNot works in the opposite way of Filter.
+func (ss carPointers) Filter(condition func(*car) bool) (ss2 carPointers) {
+	for _, s := range ss {
+		if condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+	return
+}
+
+// FilterNot works the same as Filter, with a negated condition. That is, it will
+// return a new slice only containing the elements that returned false from the
+// condition. The returned slice may contain zero elements (nil).
+func (ss carPointers) FilterNot(condition func(*car) bool) (ss2 carPointers) {
+	for _, s := range ss {
+		if !condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+
+	return
+}
+
 // First returns the first element, or zero. Also see FirstOr().
 func (ss carPointers) First() *car {
 	return ss.FirstOr(&car{})
@@ -159,6 +185,25 @@ func (ss carPointers) Len() int {
 	return len(ss)
 }
 
+// Map will return a new slice where each element has been mapped (transformed).
+// The number of elements returned will always be the same as the input.
+//
+// Be careful when using this with slices of pointers. If you modify the input
+// value it will affect the original slice. Be sure to return a new allocated
+// object or deep copy the existing one.
+func (ss carPointers) Map(fn func(*car) *car) (ss2 carPointers) {
+	if ss == nil {
+		return nil
+	}
+
+	ss2 = make([]*car, len(ss))
+	for i, s := range ss {
+		ss2[i] = fn(s)
+	}
+
+	return
+}
+
 // Random returns a random element by your rand.Source, or zero
 func (ss carPointers) Random(source rand.Source) *car {
 	n := len(ss)
@@ -214,20 +259,6 @@ func (ss carPointers) Send(ctx context.Context, ch chan<- *car) carPointers {
 	return ss
 }
 
-// Select will return a new slice containing only the elements that return
-// true from the condition. The returned slice may contain zero elements (nil).
-//
-// Unselect works in the opposite way as Select.
-func (ss carPointers) Select(condition func(*car) bool) (ss2 carPointers) {
-	for _, s := range ss {
-		if condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
-
 // Shuffle returns shuffled slice by your rand.Source
 func (ss carPointers) Shuffle(source rand.Source) carPointers {
 	n := len(ss)
@@ -280,35 +311,3 @@ func (ss carPointers) ToStrings(transform func(*car) string) Strings {
 
 	return result
 }
-
-// Transform will return a new slice where each element has been transformed.
-// The number of element returned will always be the same as the input.
-//
-// Be careful when using this with slices of pointers. If you modify the input
-// value it will affect the original slice. Be sure to return a new allocated
-// object or deep copy the existing one.
-func (ss carPointers) Transform(fn func(*car) *car) (ss2 carPointers) {
-	if ss == nil {
-		return nil
-	}
-
-	ss2 = make([]*car, len(ss))
-	for i, s := range ss {
-		ss2[i] = fn(s)
-	}
-
-	return
-}
-
-// Unselect works the same as Select, with a negated condition. That is, it will
-// return a new slice only containing the elements that returned false from the
-// condition. The returned slice may contain zero elements (nil).
-func (ss carPointers) Unselect(condition func(*car) bool) (ss2 carPointers) {
-	for _, s := range ss {
-		if !condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
diff --git a/pie/cars_pie.go b/pie/cars_pie.go
index a9978a4..e783b1a 100755
--- a/pie/cars_pie.go
+++ b/pie/cars_pie.go
@@ -110,6 +110,32 @@ func (ss cars) Extend(slices ...cars) (ss2 cars) {
 	return ss2
 }
 
+// Filter will return a new slice containing only the elements that return
+// true from the condition. The returned slice may contain zero elements (nil).
+//
+// FilterNot works in the opposite way of Filter.
+func (ss cars) Filter(condition func(car) bool) (ss2 cars) {
+	for _, s := range ss {
+		if condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+	return
+}
+
+// FilterNot works the same as Filter, with a negated condition. That is, it will
+// return a new slice only containing the elements that returned false from the
+// condition. The returned slice may contain zero elements (nil).
+func (ss cars) FilterNot(condition func(car) bool) (ss2 cars) {
+	for _, s := range ss {
+		if !condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+
+	return
+}
+
 // First returns the first element, or zero. Also see FirstOr().
 func (ss cars) First() car {
 	return ss.FirstOr(car{})
@@ -159,6 +185,25 @@ func (ss cars) Len() int {
 	return len(ss)
 }
 
+// Map will return a new slice where each element has been mapped (transformed).
+// The number of elements returned will always be the same as the input.
+//
+// Be careful when using this with slices of pointers. If you modify the input
+// value it will affect the original slice. Be sure to return a new allocated
+// object or deep copy the existing one.
+func (ss cars) Map(fn func(car) car) (ss2 cars) {
+	if ss == nil {
+		return nil
+	}
+
+	ss2 = make([]car, len(ss))
+	for i, s := range ss {
+		ss2[i] = fn(s)
+	}
+
+	return
+}
+
 // Random returns a random element by your rand.Source, or zero
 func (ss cars) Random(source rand.Source) car {
 	n := len(ss)
@@ -214,20 +259,6 @@ func (ss cars) Send(ctx context.Context, ch chan<- car) cars {
 	return ss
 }
 
-// Select will return a new slice containing only the elements that return
-// true from the condition. The returned slice may contain zero elements (nil).
-//
-// Unselect works in the opposite way as Select.
-func (ss cars) Select(condition func(car) bool) (ss2 cars) {
-	for _, s := range ss {
-		if condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
-
 // Shuffle returns shuffled slice by your rand.Source
 func (ss cars) Shuffle(source rand.Source) cars {
 	n := len(ss)
@@ -280,35 +311,3 @@ func (ss cars) ToStrings(transform func(car) string) Strings {
 
 	return result
 }
-
-// Transform will return a new slice where each element has been transformed.
-// The number of element returned will always be the same as the input.
-//
-// Be careful when using this with slices of pointers. If you modify the input
-// value it will affect the original slice. Be sure to return a new allocated
-// object or deep copy the existing one.
-func (ss cars) Transform(fn func(car) car) (ss2 cars) {
-	if ss == nil {
-		return nil
-	}
-
-	ss2 = make([]car, len(ss))
-	for i, s := range ss {
-		ss2[i] = fn(s)
-	}
-
-	return
-}
-
-// Unselect works the same as Select, with a negated condition. That is, it will
-// return a new slice only containing the elements that returned false from the
-// condition. The returned slice may contain zero elements (nil).
-func (ss cars) Unselect(condition func(car) bool) (ss2 cars) {
-	for _, s := range ss {
-		if !condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
diff --git a/pie/float64s_pie.go b/pie/float64s_pie.go
index 479949e..1628567 100755
--- a/pie/float64s_pie.go
+++ b/pie/float64s_pie.go
@@ -145,6 +145,32 @@ func (ss Float64s) Extend(slices ...Float64s) (ss2 Float64s) {
 	return ss2
 }
 
+// Filter will return a new slice containing only the elements that return
+// true from the condition. The returned slice may contain zero elements (nil).
+//
+// FilterNot works in the opposite way of Filter.
+func (ss Float64s) Filter(condition func(float64) bool) (ss2 Float64s) {
+	for _, s := range ss {
+		if condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+	return
+}
+
+// FilterNot works the same as Filter, with a negated condition. That is, it will
+// return a new slice only containing the elements that returned false from the
+// condition. The returned slice may contain zero elements (nil).
+func (ss Float64s) FilterNot(condition func(float64) bool) (ss2 Float64s) {
+	for _, s := range ss {
+		if !condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+
+	return
+}
+
 // First returns the first element, or zero. Also see FirstOr().
 func (ss Float64s) First() float64 {
 	return ss.FirstOr(0)
@@ -194,6 +220,25 @@ func (ss Float64s) Len() int {
 	return len(ss)
 }
 
+// Map will return a new slice where each element has been mapped (transformed).
+// The number of elements returned will always be the same as the input.
+//
+// Be careful when using this with slices of pointers. If you modify the input
+// value it will affect the original slice. Be sure to return a new allocated
+// object or deep copy the existing one.
+func (ss Float64s) Map(fn func(float64) float64) (ss2 Float64s) {
+	if ss == nil {
+		return nil
+	}
+
+	ss2 = make([]float64, len(ss))
+	for i, s := range ss {
+		ss2[i] = fn(s)
+	}
+
+	return
+}
+
 // Max is the maximum value, or zero.
 func (ss Float64s) Max() (max float64) {
 	if len(ss) == 0 {
@@ -305,20 +350,6 @@ func (ss Float64s) Send(ctx context.Context, ch chan<- float64) Float64s {
 	return ss
 }
 
-// Select will return a new slice containing only the elements that return
-// true from the condition. The returned slice may contain zero elements (nil).
-//
-// Unselect works in the opposite way as Select.
-func (ss Float64s) Select(condition func(float64) bool) (ss2 Float64s) {
-	for _, s := range ss {
-		if condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
-
 // Sort works similar to sort.Float64s(). However, unlike sort.Float64s the
 // slice returned will be reallocated as to not modify the input slice.
 //
@@ -401,25 +432,6 @@ func (ss Float64s) ToStrings(transform func(float64) string) Strings {
 	return result
 }
 
-// Transform will return a new slice where each element has been transformed.
-// The number of element returned will always be the same as the input.
-//
-// Be careful when using this with slices of pointers. If you modify the input
-// value it will affect the original slice. Be sure to return a new allocated
-// object or deep copy the existing one.
-func (ss Float64s) Transform(fn func(float64) float64) (ss2 Float64s) {
-	if ss == nil {
-		return nil
-	}
-
-	ss2 = make([]float64, len(ss))
-	for i, s := range ss {
-		ss2[i] = fn(s)
-	}
-
-	return
-}
-
 // Unique returns a new slice with all of the unique values.
 //
 // The items will be returned in a randomized order, even with the same input.
@@ -450,16 +462,3 @@ func (ss Float64s) Unique() Float64s {
 
 	return uniqueValues
 }
-
-// Unselect works the same as Select, with a negated condition. That is, it will
-// return a new slice only containing the elements that returned false from the
-// condition. The returned slice may contain zero elements (nil).
-func (ss Float64s) Unselect(condition func(float64) bool) (ss2 Float64s) {
-	for _, s := range ss {
-		if !condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
diff --git a/pie/ints_pie.go b/pie/ints_pie.go
index a0e49b7..79cce7b 100755
--- a/pie/ints_pie.go
+++ b/pie/ints_pie.go
@@ -145,6 +145,32 @@ func (ss Ints) Extend(slices ...Ints) (ss2 Ints) {
 	return ss2
 }
 
+// Filter will return a new slice containing only the elements that return
+// true from the condition. The returned slice may contain zero elements (nil).
+//
+// FilterNot works in the opposite way of Filter.
+func (ss Ints) Filter(condition func(int) bool) (ss2 Ints) {
+	for _, s := range ss {
+		if condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+	return
+}
+
+// FilterNot works the same as Filter, with a negated condition. That is, it will
+// return a new slice only containing the elements that returned false from the
+// condition. The returned slice may contain zero elements (nil).
+func (ss Ints) FilterNot(condition func(int) bool) (ss2 Ints) {
+	for _, s := range ss {
+		if !condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+
+	return
+}
+
 // First returns the first element, or zero. Also see FirstOr().
 func (ss Ints) First() int {
 	return ss.FirstOr(0)
@@ -194,6 +220,25 @@ func (ss Ints) Len() int {
 	return len(ss)
 }
 
+// Map will return a new slice where each element has been mapped (transformed).
+// The number of elements returned will always be the same as the input.
+//
+// Be careful when using this with slices of pointers. If you modify the input
+// value it will affect the original slice. Be sure to return a new allocated
+// object or deep copy the existing one.
+func (ss Ints) Map(fn func(int) int) (ss2 Ints) {
+	if ss == nil {
+		return nil
+	}
+
+	ss2 = make([]int, len(ss))
+	for i, s := range ss {
+		ss2[i] = fn(s)
+	}
+
+	return
+}
+
 // Max is the maximum value, or zero.
 func (ss Ints) Max() (max int) {
 	if len(ss) == 0 {
@@ -305,20 +350,6 @@ func (ss Ints) Send(ctx context.Context, ch chan<- int) Ints {
 	return ss
 }
 
-// Select will return a new slice containing only the elements that return
-// true from the condition. The returned slice may contain zero elements (nil).
-//
-// Unselect works in the opposite way as Select.
-func (ss Ints) Select(condition func(int) bool) (ss2 Ints) {
-	for _, s := range ss {
-		if condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
-
 // Sort works similar to sort.Ints(). However, unlike sort.Ints the
 // slice returned will be reallocated as to not modify the input slice.
 //
@@ -401,25 +432,6 @@ func (ss Ints) ToStrings(transform func(int) string) Strings {
 	return result
 }
 
-// Transform will return a new slice where each element has been transformed.
-// The number of element returned will always be the same as the input.
-//
-// Be careful when using this with slices of pointers. If you modify the input
-// value it will affect the original slice. Be sure to return a new allocated
-// object or deep copy the existing one.
-func (ss Ints) Transform(fn func(int) int) (ss2 Ints) {
-	if ss == nil {
-		return nil
-	}
-
-	ss2 = make([]int, len(ss))
-	for i, s := range ss {
-		ss2[i] = fn(s)
-	}
-
-	return
-}
-
 // Unique returns a new slice with all of the unique values.
 //
 // The items will be returned in a randomized order, even with the same input.
@@ -450,16 +462,3 @@ func (ss Ints) Unique() Ints {
 
 	return uniqueValues
 }
-
-// Unselect works the same as Select, with a negated condition. That is, it will
-// return a new slice only containing the elements that returned false from the
-// condition. The returned slice may contain zero elements (nil).
-func (ss Ints) Unselect(condition func(int) bool) (ss2 Ints) {
-	for _, s := range ss {
-		if !condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
diff --git a/pie/strings_pie.go b/pie/strings_pie.go
index c9ec05e..9c28f3f 100755
--- a/pie/strings_pie.go
+++ b/pie/strings_pie.go
@@ -125,6 +125,32 @@ func (ss Strings) Extend(slices ...Strings) (ss2 Strings) {
 	return ss2
 }
 
+// Filter will return a new slice containing only the elements that return
+// true from the condition. The returned slice may contain zero elements (nil).
+//
+// FilterNot works in the opposite way of Filter.
+func (ss Strings) Filter(condition func(string) bool) (ss2 Strings) {
+	for _, s := range ss {
+		if condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+	return
+}
+
+// FilterNot works the same as Filter, with a negated condition. That is, it will
+// return a new slice only containing the elements that returned false from the
+// condition. The returned slice may contain zero elements (nil).
+func (ss Strings) FilterNot(condition func(string) bool) (ss2 Strings) {
+	for _, s := range ss {
+		if !condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+
+	return
+}
+
 // First returns the first element, or zero. Also see FirstOr().
 func (ss Strings) First() string {
 	return ss.FirstOr("")
@@ -187,6 +213,25 @@ func (ss Strings) Len() int {
 	return len(ss)
 }
 
+// Map will return a new slice where each element has been mapped (transformed).
+// The number of elements returned will always be the same as the input.
+//
+// Be careful when using this with slices of pointers. If you modify the input
+// value it will affect the original slice. Be sure to return a new allocated
+// object or deep copy the existing one.
+func (ss Strings) Map(fn func(string) string) (ss2 Strings) {
+	if ss == nil {
+		return nil
+	}
+
+	ss2 = make([]string, len(ss))
+	for i, s := range ss {
+		ss2[i] = fn(s)
+	}
+
+	return
+}
+
 // Max is the maximum value, or zero.
 func (ss Strings) Max() (max string) {
 	if len(ss) == 0 {
@@ -274,20 +319,6 @@ func (ss Strings) Send(ctx context.Context, ch chan<- string) Strings {
 	return ss
 }
 
-// Select will return a new slice containing only the elements that return
-// true from the condition. The returned slice may contain zero elements (nil).
-//
-// Unselect works in the opposite way as Select.
-func (ss Strings) Select(condition func(string) bool) (ss2 Strings) {
-	for _, s := range ss {
-		if condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
-
 // Sort works similar to sort.Strings(). However, unlike sort.Strings the
 // slice returned will be reallocated as to not modify the input slice.
 //
@@ -361,25 +392,6 @@ func (ss Strings) ToStrings(transform func(string) string) Strings {
 	return result
 }
 
-// Transform will return a new slice where each element has been transformed.
-// The number of element returned will always be the same as the input.
-//
-// Be careful when using this with slices of pointers. If you modify the input
-// value it will affect the original slice. Be sure to return a new allocated
-// object or deep copy the existing one.
-func (ss Strings) Transform(fn func(string) string) (ss2 Strings) {
-	if ss == nil {
-		return nil
-	}
-
-	ss2 = make([]string, len(ss))
-	for i, s := range ss {
-		ss2[i] = fn(s)
-	}
-
-	return
-}
-
 // Unique returns a new slice with all of the unique values.
 //
 // The items will be returned in a randomized order, even with the same input.
@@ -410,16 +422,3 @@ func (ss Strings) Unique() Strings {
 
 	return uniqueValues
 }
-
-// Unselect works the same as Select, with a negated condition. That is, it will
-// return a new slice only containing the elements that returned false from the
-// condition. The returned slice may contain zero elements (nil).
-func (ss Strings) Unselect(condition func(string) bool) (ss2 Strings) {
-	for _, s := range ss {
-		if !condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
diff --git a/template.go b/template.go
index f3a835f..469028f 100644
--- a/template.go
+++ b/template.go
@@ -167,6 +167,36 @@ func (ss SliceType) Extend(slices ...SliceType) (ss2 SliceType) {
 
 	return ss2
 }
+`,
+	"Filter": `package functions
+
+// Filter will return a new slice containing only the elements that return
+// true from the condition. The returned slice may contain zero elements (nil).
+//
+// FilterNot works in the opposite way of Filter.
+func (ss SliceType) Filter(condition func(ElementType) bool) (ss2 SliceType) {
+	for _, s := range ss {
+		if condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+	return
+}
+`,
+	"FilterNot": `package functions
+
+// FilterNot works the same as Filter, with a negated condition. That is, it will
+// return a new slice only containing the elements that returned false from the
+// condition. The returned slice may contain zero elements (nil).
+func (ss SliceType) FilterNot(condition func(ElementType) bool) (ss2 SliceType) {
+	for _, s := range ss {
+		if !condition(s) {
+			ss2 = append(ss2, s)
+		}
+	}
+
+	return
+}
 `,
 	"First": `package functions
 
@@ -269,6 +299,27 @@ func (ss SliceType) LastOr(defaultValue ElementType) ElementType {
 func (ss SliceType) Len() int {
 	return len(ss)
 }
+`,
+	"Map": `package functions
+
+// Map will return a new slice where each element has been mapped (transformed).
+// The number of elements returned will always be the same as the input.
+//
+// Be careful when using this with slices of pointers. If you modify the input
+// value it will affect the original slice. Be sure to return a new allocated
+// object or deep copy the existing one.
+func (ss SliceType) Map(fn func(ElementType) ElementType) (ss2 SliceType) {
+	if ss == nil {
+		return nil
+	}
+
+	ss2 = make([]ElementType, len(ss))
+	for i, s := range ss {
+		ss2[i] = fn(s)
+	}
+
+	return
+}
 `,
 	"Max": `package functions
 
@@ -375,22 +426,6 @@ func (ss SliceType) Reverse() SliceType {
 
 	return sorted
 }
-`,
-	"Select": `package functions
-
-// Select will return a new slice containing only the elements that return
-// true from the condition. The returned slice may contain zero elements (nil).
-//
-// Unselect works in the opposite way as Select.
-func (ss SliceType) Select(condition func(ElementType) bool) (ss2 SliceType) {
-	for _, s := range ss {
-		if condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
 `,
 	"Send": `package functions
 
@@ -521,27 +556,6 @@ func (ss SliceType) Top(n int) (top SliceType) {
 
 	return
 }
-`,
-	"Transform": `package functions
-
-// Transform will return a new slice where each element has been transformed.
-// The number of element returned will always be the same as the input.
-//
-// Be careful when using this with slices of pointers. If you modify the input
-// value it will affect the original slice. Be sure to return a new allocated
-// object or deep copy the existing one.
-func (ss SliceType) Transform(fn func(ElementType) ElementType) (ss2 SliceType) {
-	if ss == nil {
-		return nil
-	}
-
-	ss2 = make([]ElementType, len(ss))
-	for i, s := range ss {
-		ss2[i] = fn(s)
-	}
-
-	return
-}
 `,
 	"Unique": `package functions
 
@@ -575,21 +589,6 @@ func (ss SliceType) Unique() SliceType {
 
 	return uniqueValues
 }
-`,
-	"Unselect": `package functions
-
-// Unselect works the same as Select, with a negated condition. That is, it will
-// return a new slice only containing the elements that returned false from the
-// condition. The returned slice may contain zero elements (nil).
-func (ss SliceType) Unselect(condition func(ElementType) bool) (ss2 SliceType) {
-	for _, s := range ss {
-		if !condition(s) {
-			ss2 = append(ss2, s)
-		}
-	}
-
-	return
-}
 `,
 	"Values": `package functions
 


Test patch:
diff --git a/pie/carpointers_test.go b/pie/carpointers_test.go
index 362ace4..c5ce348 100644
--- a/pie/carpointers_test.go
+++ b/pie/carpointers_test.go
@@ -44,12 +44,12 @@ func TestCarPointers_Contains(t *testing.T) {
 	}
 }
 
-var carPointersSelectTests = []struct {
+var carPointersFilterTests = []struct {
 	ss                carPointers
 	condition         func(*car) bool
-	expectedSelect    carPointers
-	expectedUnselect  carPointers
-	expectedTransform carPointers
+	expectedFilter    carPointers
+	expectedFilterNot carPointers
+	expectedMap       carPointers
 }{
 	{
 		nil,
@@ -71,29 +71,29 @@ var carPointersSelectTests = []struct {
 	},
 }
 
-func TestCarPointers_Select(t *testing.T) {
-	for _, test := range carPointersSelectTests {
+func TestCarPointers_Filter(t *testing.T) {
+	for _, test := range carPointersFilterTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableCarPointers(t, &test.ss)()
-			assert.Equal(t, test.expectedSelect, test.ss.Select(test.condition))
+			assert.Equal(t, test.expectedFilter, test.ss.Filter(test.condition))
 		})
 	}
 }
 
-func TestCarPointers_Unselect(t *testing.T) {
-	for _, test := range carPointersSelectTests {
+func TestCarPointers_FilterNot(t *testing.T) {
+	for _, test := range carPointersFilterTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableCarPointers(t, &test.ss)()
-			assert.Equal(t, test.expectedUnselect, test.ss.Unselect(test.condition))
+			assert.Equal(t, test.expectedFilterNot, test.ss.FilterNot(test.condition))
 		})
 	}
 }
 
-func TestCarPointers_Transform(t *testing.T) {
-	for _, test := range carPointersSelectTests {
+func TestCarPointers_Map(t *testing.T) {
+	for _, test := range carPointersFilterTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableCarPointers(t, &test.ss)()
-			assert.Equal(t, test.expectedTransform, test.ss.Transform(func(c *car) *car {
+			assert.Equal(t, test.expectedMap, test.ss.Map(func(c *car) *car {
 				return &car{
 					Name:  strings.ToUpper(c.Name),
 					Color: c.Color,
diff --git a/pie/cars_test.go b/pie/cars_test.go
index 01be965..7706f94 100644
--- a/pie/cars_test.go
+++ b/pie/cars_test.go
@@ -35,12 +35,12 @@ func TestCars_Contains(t *testing.T) {
 	}
 }
 
-var carsSelectTests = []struct {
+var carsFilterTests = []struct {
 	ss                cars
 	condition         func(car) bool
-	expectedSelect    cars
-	expectedUnselect  cars
-	expectedTransform cars
+	expectedFilter    cars
+	expectedFilterNot cars
+	expectedMap       cars
 }{
 	{
 		nil,
@@ -62,29 +62,29 @@ var carsSelectTests = []struct {
 	},
 }
 
-func TestCars_Select(t *testing.T) {
-	for _, test := range carsSelectTests {
+func TestCars_Filter(t *testing.T) {
+	for _, test := range carsFilterTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableCars(t, &test.ss)()
-			assert.Equal(t, test.expectedSelect, test.ss.Select(test.condition))
+			assert.Equal(t, test.expectedFilter, test.ss.Filter(test.condition))
 		})
 	}
 }
 
-func TestCars_Unselect(t *testing.T) {
-	for _, test := range carsSelectTests {
+func TestCars_FilterNot(t *testing.T) {
+	for _, test := range carsFilterTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableCars(t, &test.ss)()
-			assert.Equal(t, test.expectedUnselect, test.ss.Unselect(test.condition))
+			assert.Equal(t, test.expectedFilterNot, test.ss.FilterNot(test.condition))
 		})
 	}
 }
 
-func TestCars_Transform(t *testing.T) {
-	for _, test := range carsSelectTests {
+func TestCars_Map(t *testing.T) {
+	for _, test := range carsFilterTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableCars(t, &test.ss)()
-			assert.Equal(t, test.expectedTransform, test.ss.Transform(func(car car) car {
+			assert.Equal(t, test.expectedMap, test.ss.Map(func(car car) car {
 				car.Name = strings.ToUpper(car.Name)
 
 				return car
diff --git a/pie/float64s_test.go b/pie/float64s_test.go
index aa183d3..ea49565 100644
--- a/pie/float64s_test.go
+++ b/pie/float64s_test.go
@@ -36,9 +36,9 @@ func TestFloat64s_Contains(t *testing.T) {
 var float64sSelectTests = []struct {
 	ss                Float64s
 	condition         func(float64) bool
-	expectedSelect    Float64s
-	expectedUnselect  Float64s
-	expectedTransform Float64s
+	expectedFilter    Float64s
+	expectedFilterNot Float64s
+	expectedMap       Float64s
 }{
 	{
 		nil,
@@ -60,29 +60,29 @@ var float64sSelectTests = []struct {
 	},
 }
 
-func TestFloat64s_Select(t *testing.T) {
+func TestFloat64s_Filter(t *testing.T) {
 	for _, test := range float64sSelectTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableFloat64s(t, &test.ss)()
-			assert.Equal(t, test.expectedSelect, test.ss.Select(test.condition))
+			assert.Equal(t, test.expectedFilter, test.ss.Filter(test.condition))
 		})
 	}
 }
 
-func TestFloat64s_Unselect(t *testing.T) {
+func TestFloat64s_FilterNot(t *testing.T) {
 	for _, test := range float64sSelectTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableFloat64s(t, &test.ss)()
-			assert.Equal(t, test.expectedUnselect, test.ss.Unselect(test.condition))
+			assert.Equal(t, test.expectedFilterNot, test.ss.FilterNot(test.condition))
 		})
 	}
 }
 
-func TestFloat64s_Transform(t *testing.T) {
+func TestFloat64s_Map(t *testing.T) {
 	for _, test := range float64sSelectTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableFloat64s(t, &test.ss)()
-			assert.Equal(t, test.expectedTransform, test.ss.Transform(func(a float64) float64 {
+			assert.Equal(t, test.expectedMap, test.ss.Map(func(a float64) float64 {
 				return a + 5.2
 			}))
 		})
diff --git a/pie/ints_test.go b/pie/ints_test.go
index bb0957e..42cba48 100644
--- a/pie/ints_test.go
+++ b/pie/ints_test.go
@@ -32,12 +32,12 @@ func TestInts_Contains(t *testing.T) {
 	}
 }
 
-var intsSelectTests = []struct {
+var intsFilterTests = []struct {
 	ss                Ints
 	condition         func(int) bool
-	expectedSelect    Ints
-	expectedUnselect  Ints
-	expectedTransform Ints
+	expectedFilter    Ints
+	expectedFilterNot Ints
+	expectedMap       Ints
 }{
 	{
 		nil,
@@ -59,26 +59,26 @@ var intsSelectTests = []struct {
 	},
 }
 
-func TestInts_Select(t *testing.T) {
-	for _, test := range intsSelectTests {
+func TestInts_Filter(t *testing.T) {
+	for _, test := range intsFilterTests {
 		t.Run("", func(t *testing.T) {
-			assert.Equal(t, test.expectedSelect, test.ss.Select(test.condition))
+			assert.Equal(t, test.expectedFilter, test.ss.Filter(test.condition))
 		})
 	}
 }
 
-func TestInts_Unselect(t *testing.T) {
-	for _, test := range intsSelectTests {
+func TestInts_FilterNot(t *testing.T) {
+	for _, test := range intsFilterTests {
 		t.Run("", func(t *testing.T) {
-			assert.Equal(t, test.expectedUnselect, test.ss.Unselect(test.condition))
+			assert.Equal(t, test.expectedFilterNot, test.ss.FilterNot(test.condition))
 		})
 	}
 }
 
-func TestInts_Transform(t *testing.T) {
-	for _, test := range intsSelectTests {
+func TestInts_Map(t *testing.T) {
+	for _, test := range intsFilterTests {
 		t.Run("", func(t *testing.T) {
-			assert.Equal(t, test.expectedTransform, test.ss.Transform(func(i int) int {
+			assert.Equal(t, test.expectedMap, test.ss.Map(func(i int) int {
 				return i + 5
 			}))
 		})
diff --git a/pie/strings_test.go b/pie/strings_test.go
index 98580fb..c36f7a1 100644
--- a/pie/strings_test.go
+++ b/pie/strings_test.go
@@ -35,12 +35,12 @@ func TestStrings_Contains(t *testing.T) {
 	}
 }
 
-var stringsSelectTests = []struct {
+var stringsFilterTests = []struct {
 	ss                Strings
 	condition         func(string) bool
-	expectedSelect    Strings
-	expectedUnselect  Strings
-	expectedTransform Strings
+	expectedFilter    Strings
+	expectedFilterNot Strings
+	expectedMap       Strings
 }{
 	{
 		nil,
@@ -62,29 +62,29 @@ var stringsSelectTests = []struct {
 	},
 }
 
-func TestStrings_Select(t *testing.T) {
-	for _, test := range stringsSelectTests {
+func TestStrings_Filter(t *testing.T) {
+	for _, test := range stringsFilterTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableStrings(t, &test.ss)()
-			assert.Equal(t, test.expectedSelect, test.ss.Select(test.condition))
+			assert.Equal(t, test.expectedFilter, test.ss.Filter(test.condition))
 		})
 	}
 }
 
-func TestStrings_Unselect(t *testing.T) {
-	for _, test := range stringsSelectTests {
+func TestStrings_FilterNot(t *testing.T) {
+	for _, test := range stringsFilterTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableStrings(t, &test.ss)()
-			assert.Equal(t, test.expectedUnselect, test.ss.Unselect(test.condition))
+			assert.Equal(t, test.expectedFilterNot, test.ss.FilterNot(test.condition))
 		})
 	}
 }
 
-func TestStrings_Transform(t *testing.T) {
-	for _, test := range stringsSelectTests {
+func TestStrings_Map(t *testing.T) {
+	for _, test := range stringsFilterTests {
 		t.Run("", func(t *testing.T) {
 			defer assertImmutableStrings(t, &test.ss)()
-			assert.Equal(t, test.expectedTransform, test.ss.Transform(strings.ToUpper))
+			assert.Equal(t, test.expectedMap, test.ss.Map(strings.ToUpper))
 		})
 	}
 }