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

Overview

🍕 github.com/elliotchance/pie

GoDoc Build Status codecov

Enjoy a slice! pie is a library of utility functions for common operations on slices and maps.

Quick Start

If you are using (or require) Go 1.17 or below, you will have to use v1.

pie can be used in two ways, the first is to use the regular parameterized functions:

Run this program

package main

import (
    "fmt"
    "strings"

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

func main() {
    names := pie.FilterNot([]string{"Bob", "Sally", "John", "Jane"},
        func(name string) bool {
            return strings.HasPrefix(name, "J")
        })

    fmt.Println(names) // "[Bob Sally]"
}

Or, if you need to chain multiple operations you can use one of:

  • pie.Of - works with any element type, but functions are limited.
  • pie.OfOrdered - only works with numbers and strings, but has more functions.
  • pie.OfNumeric - only works with numbers, but has all functions.

Run this program

package main

import (
    "fmt"
    "strings"

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

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

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

You can find the full documentation here.

FAQ

What are the requirements?

pie v2 only supports Go 1.18+. If you have an older version you can use v1.

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 (except in cases where it would be illogical), 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 for your function (tip: copy an existing file can be quicker). Add your implmentation and comment.

  2. Create appropriate tests.

  3. If your function accepts a slice, it should also be added to the OfSlice API (see of.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.

Issues
  • generate for custom types

    generate for custom types

    This is all about type safety, it would make sense then to be able to generate all these functions (and more) for any given type. If this makes sense, I might try to contribute a PR with this

    enhancement 
    opened by ghostsquad 9
  • Undefined method

    Undefined method

    Hi @elliotchance, Anyone could tell me what step am I missing when run go generate ./... && go install && go generate ./...? List error attached below Screen Shot 2019-05-07 at 4 39 05 PM Thanks in advance!

    opened by hiepndd 6
  • Intersect

    Intersect

    As for signature, func (ss SliceType) Intersect(slices ...SliceType) (ss2 SliceType) I've decided to do that couse it can be useful immediately intersect several slices. In cases like this and many others.

     var userInterests = Strings{"Football", "Volleyball"}
     theSameInterests :=  userInterests.Intersect(friendsInterests...)
     ...
    
    

    As for realisation, I wonder, should I have been able to use map for it? That closes #71


    This change is Reviewable

    opened by zhiburt 6
  • Select vs Filter

    Select vs Filter

    Hey,

    This lib looks really neat, thank you & good job! :+1:

    Just one thing that kind of surprised me. The Filter method is called Select here. There are quite a few languages that have the terminology for Filter. I don't really know Select from other languages, but that might be my ignorance :smile:.

    I believe that a lot of people will ook for a Filter method (I tried before finding out it's Select).What do you think of renaming it to Filter? (It does break the symmetry between Select and Unselect. But I also think Unselect is not a common name).

    For comparison, here is a list of names for the "Filter" function in different languages: https://en.wikipedia.org/wiki/Filter_(higher-order_function). Only mathematica seems to be using the Select terminology.

    So, in short. I'd say Select -> Filter to make it easier for people to find/understand which method they need. What do you think?

    I'd want to contribute this change. But I first want to know your opinion. Maybe my concern is unfounded :sweat_smile: Not to mention this will break some dependencies. Unless we can introduce a synonym and have both Filter/Select. (They can point to the same implementation, so it'd just be kind of like a "typedef").

    opened by DylanMeeus 6
  • Median in O(n) average performance

    Median in O(n) average performance

    Hi, Median currently does alloc + Sort, for a total cost O(n log n).

    I think we can achieve alloc + custom code, for a total cost O(n) on average.

    Shall I do impl, tests, benchmarks, and PR? This would be mergeable if the large case is improved, and the small case not degraded.

    question 
    opened by Deleplace 5
  • Implementation of Top and Bottom functions

    Implementation of Top and Bottom functions

    That closes #23

    As for Bottom function I'm not confident about implementation This function returns elements from the end Might it be better to return them from another side?

    PS. It's my first pull request in not my project So if there are problems please give some feedback


    This change is Reviewable

    opened by zhiburt 5
  • added: JSONBytes

    added: 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.


    This change is Reviewable

    opened by kochurovro 4
  • Diff: unexpected behaviour

    Diff: unexpected behaviour

    firstSlice := pie.Ints{1, 2, 3, 3, 4, 4}
    secondSlice := pie.Ints{3, 4, 5, 4, 6}
    fmt.Println(firstSlice.Diff(secondSlice))
    

    panic: runtime error: slice bounds out of range [5:4]

    bug 
    opened by andriyor 3
  • Each: fix example in comment

    Each: fix example in comment

    Using the example

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

    I get the error:

    ./main.go:31:18: cannot use func literal (type func(*Car)) as type func(Car) in argument to myCars.Each
    

    This change is Reviewable

    opened by AlessandroLorenzi 3
  • SequenceUsing

    SequenceUsing

    Hi @elliotchance, What do you think about this function's signature SequenceUsing(creator func(int) ElementType, params ...int) SliceType.

    That closes #107.


    This change is Reviewable

    opened by zhiburt 3
  • Sequence

    Sequence

    closes #70 I've done it with comment which I had written in #70.

    As for negative sequences, I suppose it is on default to support it. I've created it as I've considered right. You could see tests. But I'd like to know your attitude to this example, as for me, I consider that's correct.

    pie.Ints{}.Sequence(-10, -5)
    // pie.Ints{-10, -9, -8, -7, -6}
    

    but

    pie.Ints{}.Sequence(-5, -10)
    // nil
    

    for do this thing you should use this one

    pie.Ints{}.Sequence(-5, -10, -1)
    // pie.Ints{-5, -6, -7, -8, -9},
    

    This change is Reviewable

    opened by zhiburt 3
  • I want to add a new Functions - Remove

    I want to add a new Functions - Remove

    I want to add remove,like:

    listA := pie.Strings{"1", "2"}
    listB := pie.Strings{"1", "3"}
          
    // [ "2" ]
    fmt.Println(listA.Remove(listB...))
    

    In some scenarios, there will be a desire to weed out the data in slice A from the data in slice B

    opened by Luoxin 1
  • problem: Equals interface

    problem: Equals interface

    As you may know there's issue #39 Problem: If you create Equals method and use it anywhere in methods generator replace that expression.

    example

    func(ss SliceType) NotEqual(rhs SliceType) bool {
       return !ss.Equals(rhs)
    }
    

    when you call go generate expression !ss.Equals(rhs) will be replaced on !(ss != rhs)

    I consider for solving this one, should check type of element which call Equals but might there be a better solution.

    question 
    opened by zhiburt 3
  • Join can be used on all types

    Join can be used on all types

    In a recent version, I introduced fmt.Stringer, see:

    https://github.com/elliotchance/pie/blob/master/functions/float64s.go#L19-L20

    mightBeString.String() will be replaced with a fmt.Sprintf("%v", mightBeString) for types that do not implement fmt.Stringer.

    The functions that support this as tagged with an "S" in the Functions list. This means that Join could be used on all types and StringSliceType can be removed :)

    enhancement 
    opened by elliotchance 0
  • Functions depending on other Functions

    Functions depending on other Functions

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	a := myFloats{1.0, 2.0, 3.0}
    	fmt.Println(a.First())
    }
    
    //go:generate pie myFloats.First
    type myFloats []float64
    

    yields

    ./myfloats_pie.go:5:11: ss.FirstOr undefined (type myFloats has no field or method FirstOr)
    

    Currently, the developer hits this error and figures out they must explicitly ask for FirstOr:

    //go:generate pie myFloats.First.FirstOr
    

    It would be nice if Pie somehow knew it requires to generate FirstOras a dependency for First. I'm not saying this is trivial though, and also the inconvenience is minor.

    bug 
    opened by Deleplace 2
Releases(v2.0.1)
Owner
Elliot Chance
I'm a data nerd and TDD enthusiast originally from Sydney, Australia. I love exploring new technologies and working on modern ways to solve age old problems.
Elliot Chance
A Go package for checking conditions for slices and maps.

check Go package The check package of Go helps one to check various conditions for slices: []int []float64 []string []bool maps: map[string]int map[st

null 4 Feb 3, 2022
Create deep copies (clones) of your maps and slices without using reflection.

DeepCopy DeepCopy helps you create deep copies (clones) of your maps and slices. Create deep copies (clones) of your objects The package is based on t

null 3 Apr 12, 2022
Optimal implementation of ordered maps for Golang - ie maps that remember the order in which keys were inserted.

Goland Ordered Maps Same as regular maps, but also remembers the order in which keys were inserted, akin to Python's collections.OrderedDicts. It offe

Jean Rougé 195 Jun 20, 2022
efaceconv - Code generation tool for high performance conversion from interface{} to immutable type without allocations.

efaceconv High performance conversion from interface{} to immutable types without additional allocations This is tool for go generate and common lib (

Ivan 50 May 14, 2022
Bitwise AND on two byte-slices using SIMD instructions

This package provides a vectorised function which performs bitwise AND operation on all pairs of elements in two byte-slices. It detects CPU instruction set and chooses the available best one (AVX512, AVX2, SSE2).

Wei Shen 5 Dec 10, 2021
A go1.18+ package to (maybe) simplify performing operations on slices in a fluent-like style.

sop ✨ W.I.P. ✨ sop (slices operation) is a go1.18+ package to (maybe) simplify performing operations on slices in a fluent-like style with common oper

Ringo Hoffmann 3 Mar 17, 2022
Access and modify property values in deeply nested maps, using dot-separated paths

Dig lets you access and modify property values in deeply nested, unstructured maps, using dot-separated paths: source := make(map[string]interface{})

Preslav Rachev 12 May 7, 2022
Automatically creates & tiles .tmx format maps from a world map interface

Autotile Create tiled maps for an arbitrarily large world space from a simple interface, then add larger objects randomly with simple rules (eg. place

null 0 Jan 9, 2022
💪 Helper Utils For The Go: string, array/slice, map, format, cli, env, filesystem, test and more.

?? Helper Utils For The Go: string, array/slice, map, format, cli, env, filesystem, test and more. Go 的一些工具函数,格式化,特殊处理,常用信息获取等等

Gookit 839 Jun 29, 2022
Tiny Go tool for running multiple functions concurrently and collecting their results into an error slice.

Overview Short for "ConCurrent". Tiny Go tool for running multiple functions concurrently and collecting their results into an error slice. Dependency

Nelo Mitranim 0 Nov 22, 2021
Wrap byte read options with uniform interface for io.Reader and byte slice

nibbler Nibble chunks from Reader streams and slice in a common way Overview This is a golang module that provides an interface for treating a Reader

null 0 Dec 23, 2021
Go 1.18 generics based slice and sorts.

genfuncs import "github.com/nwillc/genfuncs" Package genfuncs implements various functions utilizing Go's Generics to help avoid writing boilerplate c

Nwillc 15 Jun 25, 2022
Slice - provides generic Map, Reduce and Filter functions for Go.

slice slice is a simple Go package to provide generic versions of Map, Reduce and Filter on slices. I mainly wrote it as an exercise to get more famil

Andreas Krennmair 17 Jun 17, 2022
make slice items unique in go

make slice items unique in go

Dariush Abbasi 3 Jan 20, 2022
Slice conversion between primitive types

sliceconv Sliceconv implements conversions to and from string representations of primitive types on entire slices. The package supports types int, flo

Henry Sarabia 8 Jan 24, 2022
Go library for HTTP content type negotiation

Content-Type support library for Go This library can be used to parse the value Content-Type header (if one is present) and select an acceptable media

Elviss Strazdins 40 May 25, 2022
safe and easy casting from one type to another in Go

cast Easy and safe casting from one type to another in Go Don’t Panic! ... Cast What is Cast? Cast is a library to convert between different go types

Steve Francia 2.4k Jun 29, 2022
A super simple Lodash like utility library with essential functions that empowers the development in Go

A simple Utility library for Go Go does not provide many essential built in functions when it comes to the data structure such as slice and map. This

Rahul Baruri 126 May 20, 2022
A utility library to do files/io/bytes processing/parsing in file-system or network.

goreader A utility library to do files/io/bytes processing/parsing in file-system or network. These features are really common to be implemented for a

VOrishirne 4 Nov 1, 2021