All Projects → elliotchance → Pie

elliotchance / Pie

Licence: mit
🍕 Enjoy a slice! A utility library for dealing with slices and maps that focuses on type safety and performance.

Programming Languages

go
31211 projects - #10 most used programming language
golang
3204 projects

Projects that are alternatives of or similar to Pie

Fakeit
The Kotlin fake data generator library!
Stars: ✭ 482 (-38.83%)
Mutual labels:  utility
Thor
Switch the right application ASAP.
Stars: ✭ 660 (-16.24%)
Mutual labels:  utility
Flix
iOS reusable form library in Swift.
Stars: ✭ 725 (-7.99%)
Mutual labels:  generics
Saws
A supercharged AWS command line interface (CLI).
Stars: ✭ 4,886 (+520.05%)
Mutual labels:  utility
Cabin
🌲 Cabin is the best JavaScript and Node.js logging service and logging npm package
Stars: ✭ 622 (-21.07%)
Mutual labels:  utility
Goto
Alias and navigate to directories with tab completion in Linux
Stars: ✭ 698 (-11.42%)
Mutual labels:  utility
K2tf
Kubernetes YAML to Terraform HCL converter
Stars: ✭ 477 (-39.47%)
Mutual labels:  utility
Engauge Digitizer
Extracts data points from images of graphs
Stars: ✭ 754 (-4.31%)
Mutual labels:  utility
Basscss
Low-level CSS Toolkit – the original Functional/Utility/Atomic CSS library
Stars: ✭ 5,669 (+619.42%)
Mutual labels:  utility
Reloading
Change Python code while it's running without losing state
Stars: ✭ 723 (-8.25%)
Mutual labels:  utility
Dozer
Hide menu bar icons on macOS
Stars: ✭ 5,655 (+617.64%)
Mutual labels:  utility
Search Deflector
A small program that forwards searches from Cortana to your preferred browser and search engine.
Stars: ✭ 620 (-21.32%)
Mutual labels:  utility
Embedmd
embedmd: embed code into markdown and keep everything in sync
Stars: ✭ 714 (-9.39%)
Mutual labels:  utility
In View
Get notified when a DOM element enters or exits the viewport. 👀
Stars: ✭ 4,684 (+494.42%)
Mutual labels:  utility
Pydash
The kitchen sink of Python utility libraries for doing "stuff" in a functional way. Based on the Lo-Dash Javascript library.
Stars: ✭ 728 (-7.61%)
Mutual labels:  utility
Git Fresh
🍋 Keep your Git repo fresh.
Stars: ✭ 480 (-39.09%)
Mutual labels:  utility
Backslide
💦 CLI tool for making HTML presentations with Remark.js using Markdown
Stars: ✭ 679 (-13.83%)
Mutual labels:  utility
Remeda
A utility library for JavaScript and TypeScript.
Stars: ✭ 774 (-1.78%)
Mutual labels:  utility
Utils
A collection of useful PHP functions, mini classes and snippets that you need and can use every day.
Stars: ✭ 750 (-4.82%)
Mutual labels:  utility
Quicktile
Adds window-tiling hotkeys to any X11 desktop. (An analogue to WinSplit Revolution for people who don't want to use Compiz Grid)
Stars: ✭ 719 (-8.76%)
Mutual labels:  utility

🍕 github.com/elliotchance/pie

GoDoc Build Status codecov

Enjoy a slice! pie is a code generator for dealing with slices that focuses on type safety, performance and immutability.

Quick Start

Install/Update

go get -u github.com/elliotchance/pie

Built-in Types

pie ships with some slice types ready to go (pun intended). These include:

These can be used without needing go generate. For example:

package main

import (
    "fmt"
    "strings"

    "github.com/elliotchance/pie/pie"
)

func main() {
    name := pie.Strings{"Bob", "Sally", "John", "Jane"}.
        FilterNot(func (name string) bool {
            return strings.HasPrefix(name, "J")
        }).
        Map(strings.ToUpper).
        Last()

    fmt.Println(name) // "SALLY"
}

Custom Types

Annotate the slice type in your source code:

type Car struct {
    Name, Color string
}

//go:generate pie Cars.*
type Cars []Car

Run go generate. This will create a file called cars_pie.go. You should commit this with the rest of your code. Run go generate any time you need to add more types.

Now you can use the slices:

cars := Cars{
    {"Bob", "blue"},
    {"Sally", "green"},
    {"John", "red"},
    {"Jane", "red"},
}

redCars := cars.Filter(func(car Car) bool {
    return car.Color == "red"
})

// redCars = Cars{{"John", "red"}, {"Jane", "red"}}

Or, more complex operations can be chained:

cars.FilterNot(func (car Car) {
        return strings.HasPrefix(car.Name, "J")
    }).
    Map(func (car Car) Car {
        car.Name = strings.ToUpper(car.Name)

        return car
    }).
    Last()

// Car{"SALLY", "green"}

Custom Equality

Some functions that compare elements, such as Contains will use the following method if it is available on the element type:

func (a ElementType) Equals(b ElementType) bool

The ElementType must be the same for the receiver and argument and it must return a bool. Be careful to create the function on the pointer or non-pointer type that is used by the slice.

Here is a minimal example:

type Car struct {
	Name, Color string
}

type Cars []*Car // ElementType is *Car

func (c *Car) Equals(c2 *Car) bool {
	return c.Name == c2.Name
}

Custom Stringer

Some functions that need elements to be represented as strings, such as Strings() will try to use the fmt.Stringer interface. If it's not available then it will fallback to:

fmt.Sprintf("%v", element)

Limiting Functions Generated

The .* can be used to generate all functions. This is easy to get going but creates a lot of unused code. You can limit the functions generated by chaining the function names with a dot syntax, like:

//go:generate pie myInts.Average.Sum myStrings.Filter

This will only generate myInts.Average, myInts.Sum and myStrings.Filter.

Functions

Below is a summary of the available functions.

The letters in brackets indicate:

  • E: The function will use the Equals method if it is available. See Custom Equality.

  • S: The function will use the String method if it is available. See Custom Stringer.

Function String Number Struct Maps Big-O Description
Abs n Abs is a function which returns the absolute value of all the elements in the slice.
All n All will return true if all callbacks return true. It follows the same logic as the all() function in Python.
Any n Any will return true if any callbacks return true. It follows the same logic as the any() function in Python.
Append n Append will return a new slice with the elements appended to the end.
AreSorted n AreSorted will return true if the slice is already sorted. It is a wrapper for sort.SliceTypeAreSorted.
AreUnique n AreUnique will return true if the slice contains elements that are all different (unique) from each other.
Average n Average is the average of all of the elements, or zero if there are no elements.
Bottom n Bottom will return n elements from bottom
Contains (E) n Contains returns true if the element exists in the slice.
Diff (E) Diff returns the elements that needs to be added or removed from the first slice to have the same elements in the second slice.
DropTop n DropTop will return the rest slice after dropping the top n elements if the slice has less elements then n that'll return empty slice if n < 0 it'll return empty slice.
Each n Each is more condensed version of Transform that allows an action to happen on each elements and pass the original slice on.
Equals (E) n Equals compare elements from the start to the end,
Extend n Extend will return a new slice with the slices of elements appended to the end.
Filter n 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 n 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).
FindFirstUsing n FindFirstUsing will return the index of the first element when the callback returns true or -1 if no element is found. It follows the same logic as the findIndex() function in Javascript.
First 1 First returns the first element, or zero. Also see FirstOr().
FirstOr 1 FirstOr returns the first element or a default value if there are no elements.
Float64s (S) n Float64s transforms each element to a float64.
Group n Group returns a map of the value with an individual count.
Intersect n Intersect returns items that exist in all lists.
Insert n Insert a value at an index
Ints (S) n Ints transforms each element to an integer.
Join (S) n Join returns a string from joining each of the elements.
JSONBytes n JSONBytes returns the JSON encoded array as bytes.
JSONBytesIndent n JSONBytesIndent returns the JSON encoded array as bytes with indent applied.
JSONString n JSONString returns the JSON encoded array as a string.
JSONStringIndent n JSONStringIndent returns the JSON encoded array as a string with indent applied.
Keys n Keys returns the keys in the map. All of the items will be unique.
Last 1 Last returns the last element, or zero. Also see LastOr().
LastOr 1 LastOr returns the last element or a default value if there are no elements.
Len 1 Len returns the number of elements.
Map n 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.
Max n Max is the maximum value, or zero.
Median n Median returns the value separating the higher half from the lower half of a data sample.
Min n Min is the minimum value, or zero.
Mode n Mode returns a new slice containing the most frequently occuring values.
Pop n Pop the first element of the slice
Product n Product is the product of all of the elements.
Random 1 Random returns a random element by your rand.Source, or zero
Reduce n Reduce continually applies the provided function over the slice. Reducing the elements to a single value.
Reverse n Reverse returns a new copy of the slice with the elements ordered in reverse. This is useful when combined with Sort to get a descending sort order:
Send n Send sends elements to channel in normal act it sends all elements but if func canceled it can be less
Sequence n Sequence generates all numbers in range or returns nil if params invalid
SequenceUsing n SequenceUsing generates slice in range using creator function
Shift n Shift will return two values: the shifted value and the rest slice.
Shuffle n Shuffle returns shuffled slice by your rand.Source
Sort n⋅log(n) Sort works similar to sort.SliceType(). However, unlike sort.SliceType the slice returned will be reallocated as to not modify the input slice.
SortStableUsing n⋅log(n) SortStableUsing works similar to sort.SliceStable. However, unlike sort.SliceStable the slice returned will be reallocated as to not modify the input slice.
SortUsing n⋅log(n) SortUsing works similar to sort.Slice. However, unlike sort.Slice the slice returned will be reallocated as to not modify the input slice.
Stddev n Stddev is the standard deviation
Strings (S) n Strings transforms each element to a string.
SubSlice n SubSlice will return the subSlice from start to end(excluded)
Sum n Sum is the sum of all of the elements.
Top n Top will return n elements from head of the slice if the slice has less elements then n that'll return all elements if n < 0 it'll return empty slice.
StringsUsing n StringsUsing transforms each element to a string.
Unique n Unique returns a new slice with all of the unique values.
Unshift n Unshift adds one or more elements to the beginning of the slice and returns the new slice.
Values n Values returns the values in the map.

Abs

Abs is a function which returns the absolute value of all the elements in the slice.

All

All will return true if all callbacks return true. It follows the same logic as the all() function in Python.

If the list is empty then true is always returned.

Any

Any will return true if any callbacks return true. It follows the same logic as the any() function in Python.

If the list is empty then false is always returned.

Append

Append will return a new slice with the elements appended to the end.

It is acceptable to provide zero arguments.

AreSorted

AreSorted will return true if the slice is already sorted. It is a wrapper for sort.SliceTypeAreSorted.

AreUnique

AreUnique will return true if the slice contains elements that are all different (unique) from each other.

Average

Average is the average of all of the elements, or zero if there are no elements.

Bottom

Bottom will return n elements from bottom

that means that elements is taken from the end of the slice for this [1,2,3] slice with n == 2 will be returned [3,2] if the slice has less elements then n that'll return all elements if n < 0 it'll return empty slice.

Contains

Contains returns true if the element exists in the slice.

When using slices of pointers it will only compare by address, not value.

Diff

Diff returns the elements that needs to be added or removed from the first slice to have the same elements in the second slice.

The order of elements is not taken into consideration, so the slices are treated sets that allow duplicate items.

The added and removed returned may be blank respectively, or contain upto as many elements that exists in the largest slice.

DropTop

DropTop will return the rest slice after dropping the top n elements if the slice has less elements then n that'll return empty slice if n < 0 it'll return empty slice.

Each

Each is more condensed version of Transform that allows an action to happen on each elements and pass the original slice on.

cars.Each(func (car *Car) {
    fmt.Printf("Car color is: %s\n", car.Color)
})

Pie will not ensure immutability on items passed in so they can be manipulated, if you choose to do it this way, for example:

// Set all car colors to Red.
cars.Each(func (car *Car) {
    car.Color = "Red"
})

Equals

Equals compare elements from the start to the end,

if they are the same is considered the slices are equal if all elements are the same is considered the slices are equal if each slice == nil is considered that they're equal

if element realizes Equals interface it uses that method, in other way uses default compare

Extend

Extend will return a new slice with the slices of elements appended to the end.

It is acceptable to provide zero arguments.

Filter

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.

FilterNot

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).

FindFirstUsing

FindFirstUsing will return the index of the first element when the callback returns true or -1 if no element is found. It follows the same logic as the findIndex() function in Javascript.

If the list is empty then -1 is always returned.

First

First returns the first element, or zero. Also see FirstOr().

FirstOr

FirstOr returns the first element or a default value if there are no elements.

Float64s

Float64s transforms each element to a float64.

Group

Group returns a map of the value with an individual count.

Intersect

Intersect returns items that exist in all lists.

It returns slice without any duplicates. If zero slice arguments are provided, then nil is returned.

Insert

Insert a value at an index

Ints

Ints transforms each element to an integer.

Join

Join returns a string from joining each of the elements.

JSONBytes

JSONBytes returns the JSON encoded array as bytes.

One important thing to note is that it will treat a nil slice as an empty slice to ensure that the JSON value return is always an array.

JSONBytesIndent

JSONBytesIndent returns the JSON encoded array as bytes with indent applied.

One important thing to note is that it will treat a nil slice as an empty slice to ensure that the JSON value return is always an array. See json.MarshalIndent for details.

JSONString

JSONString returns the JSON encoded array as a string.

One important thing to note is that it will treat a nil slice as an empty slice to ensure that the JSON value return is always an array.

JSONStringIndent

JSONStringIndent returns the JSON encoded array as a string with indent applied.

One important thing to note is that it will treat a nil slice as an empty slice to ensure that the JSON value return is always an array. See json.MarshalIndent for details.

Keys

Keys returns the keys in the map. All of the items will be unique.

Due to Go's randomization of iterating maps the order is not deterministic.

Last

Last returns the last element, or zero. Also see LastOr().

LastOr

LastOr returns the last element or a default value if there are no elements.

Len

Len returns the number of elements.

Map

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.

Max

Max is the maximum value, or zero.

Median

Median returns the value separating the higher half from the lower half of a data sample.

Zero is returned if there are no elements in the slice.

If the number of elements is even, then the ElementType mean of the two "median values" is returned.

Min

Min is the minimum value, or zero.

Mode

Mode returns a new slice containing the most frequently occuring values.

The number of items returned may be the same as the input or less. It will never return zero items unless the input slice has zero items.

Pop

Pop the first element of the slice

Usage Example:

type knownGreetings []string
greetings := knownGreetings{"ciao", "hello", "hola"}
for greeting := greetings.Pop(); greeting != nil; greeting = greetings.Pop() {
    fmt.Println(*greeting)
}

Product

Product is the product of all of the elements.

Random

Random returns a random element by your rand.Source, or zero

Reduce

Reduce continually applies the provided function over the slice. Reducing the elements to a single value.

Returns a zero value of ElementType if there are no elements in the slice. It will panic if the reducer is nil and the slice has more than one element (required to invoke reduce). Otherwise returns result of applying reducer from left to right.

Reverse

Reverse returns a new copy of the slice with the elements ordered in reverse. This is useful when combined with Sort to get a descending sort order:

ss.Sort().Reverse()

Send

Send sends elements to channel in normal act it sends all elements but if func canceled it can be less

it locks execution of gorutine it doesn't close channel after work returns sended elements if len(this) != len(old) considered func was canceled

Sequence

Sequence generates all numbers in range or returns nil if params invalid

There are 3 variations to generate: 1. [0, n). 2. [min, max). 3. [min, max) with step.

if len(params) == 1 considered that will be returned slice between 0 and n, where n is the first param, [0, n). if len(params) == 2 considered that will be returned slice between min and max, where min is the first param, max is the second, [min, max). if len(params) > 2 considered that will be returned slice between min and max with step, where min is the first param, max is the second, step is the third one, [min, max) with step, others params will be ignored

SequenceUsing

SequenceUsing generates slice in range using creator function

There are 3 variations to generate: 1. [0, n). 2. [min, max). 3. [min, max) with step.

if len(params) == 1 considered that will be returned slice between 0 and n, where n is the first param, [0, n). if len(params) == 2 considered that will be returned slice between min and max, where min is the first param, max is the second, [min, max). if len(params) > 2 considered that will be returned slice between min and max with step, where min is the first param, max is the second, step is the third one, [min, max) with step, others params will be ignored

Shift

Shift will return two values: the shifted value and the rest slice.

Shuffle

Shuffle returns shuffled slice by your rand.Source

Sort

Sort works similar to sort.SliceType(). However, unlike sort.SliceType the slice returned will be reallocated as to not modify the input slice.

See Reverse() and AreSorted().

SortStableUsing

SortStableUsing works similar to sort.SliceStable. However, unlike sort.SliceStable the slice returned will be reallocated as to not modify the input slice.

SortUsing

SortUsing works similar to sort.Slice. However, unlike sort.Slice the slice returned will be reallocated as to not modify the input slice.

Stddev

Stddev is the standard deviation

Strings

Strings transforms each element to a string.

If the element type implements fmt.Stringer it will be used. Otherwise it will fallback to the result of:

fmt.Sprintf("%v")

SubSlice

SubSlice will return the subSlice from start to end(excluded)

Condition 1: If start < 0 or end < 0, nil is returned. Condition 2: If start >= end, nil is returned. Condition 3: Return all elements that exist in the range provided, if start or end is out of bounds, zero items will be placed.

Sum

Sum is the sum of all of the elements.

Top

Top will return n elements from head of the slice if the slice has less elements then n that'll return all elements if n < 0 it'll return empty slice.

StringsUsing

StringsUsing transforms each element to a string.

Unique

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.

The number of items returned may be the same as the input or less. It will never return zero items unless then input slice has zero items.

A slice with zero elements is considered to be unique.

See AreUnique().

Unshift

Unshift adds one or more elements to the beginning of the slice and returns the new slice.

Values

Values returns the values in the map.

Due to Go's randomization of iterating maps the order is not deterministic.

FAQ

What are the requirements?

pie supports many Go versions, all the way back to Go 1.8.

What are the goals of pie?

  1. Type safety. I never want to hit runtime bugs because I could pass in the wrong type, or perform an invalid type case out the other end.

  2. Performance. The functions need to be as fast as native Go implementations otherwise there's no point in this library existing.

  3. Nil-safe. All of the functions will happily accept nil and treat them as empty slices. Apart from less possible panics, it makes it easier to chain.

  4. Immutable. Functions never modify inputs, unlike some built-ins such as sort.Strings.

How do I contribute a function?

Pull requests are always welcome.

Here is a comprehensive list of steps to follow to add a new function:

  1. Create a new file in the functions/ directory. The file should be named the same as the function. You must include documentation for your function.

  2. Update functions/main.go to register the new function by adding an entry to Functions. Make sure you choose the correct For value that is appropriate for your function.

  3. Run go generate ./... && go install && go generate ./.... The first generate is to create the pie templates, install will update your binary for the annotations and the second generate will use the newly created templates to update the generated code for the internal types. If you encounter errors with your code you can safely rerun the command above.

  4. If you chose ForAll or ForStructs, then you must add unit tests to pie/carpointers_test.go and pie/cars_test.go.

  5. If you chose ForAll, ForNumbersAndStrings or ForNumbers, then you must add unit tests to pie/float64s_test.go and pie/ints_test.go.

  6. If you chose ForAll or ForStrings, then you must add unit tests to pie/strings_test.go.

  7. If you chose ForMaps, then you must add unit tests to pie/currencies.go.

Why is the emoji a slice of pizza instead of a pie?

I wanted to pick a name for the project that was short and had an associated emoji. I liked pie, but then I found out that the pie emoji is not fully supported everywhere. I didn't want to change the name of the project to cake, but pizza pie still made sense. I'm not sure if I will change it back to a pie later.

How do I exclude generated files from code coverage?

Go does not provide a way to exclude code coverage from specific files or lines with comments. However, you can remove the _pie.go files from the code coverage report before it is published:

go test -race -coverprofile=coverage.txt -covermode=atomic
sed -i '/_pie\.go/d' ./coverage.txt

If you are running on macOS, you will need a slightly different syntax for sed:

sed -i '' /_pie\.go/d' ./coverage.txt
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].