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

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

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
Comments
  • 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

  • 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!

  • 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

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

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

  • 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

  • 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

  • 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]

  • 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

  • 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

  • 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

  • added Chunk

    added Chunk

    add feat: SplitSlice SplitSlice returns splited slices which length equals splitLength. This is useful in scenarios such as request or saving data in batch when the size of transport data per time is limited.

  • 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

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

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

Aug 26, 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

Nov 20, 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

Jan 3, 2023
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 (

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

Oct 17, 2022
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

Oct 1, 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{})

May 7, 2022
Automatically creates & tiles .tmx format maps from a world map interface
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

Aug 19, 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.

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

Jan 6, 2023
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

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

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

Jan 2, 2023
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

Jan 1, 2023
make slice items unique in go

make slice items unique in go

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

Sep 27, 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

Jul 10, 2022
A super simple Lodash like utility library with essential functions that empowers the development in Go
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

Jan 4, 2023
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

Nov 1, 2021
Utility library that uses Go generics mechanism

golang-generics-util Utility library that explores Go generics (1.18) xsync Sync

Dec 11, 2022