gofp

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 22, 2021 License: MIT Imports: 5 Imported by: 0

README

gofp

Go test workflow Go Report Card Go Reference codecov

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 library provides a list of most frequently needed utility functions which are inspired by lodash(a Javascript Utility library).

Main features of gofp

  • Implementing Functional programming is way easier using Pipe(), Compose(), Reduce(), Map(), Filter(), Extend(), Find() and many others.

  • This library offers many utility function for dealing with collections or slice related operation.

  • Access any property by path or index from the map, slice and even struct by simply using the most useful function Get.

  • Utility functions are implmented based on interface{}. The main focus is not to use the reflect package whenever possible.

Installation

Please run the following command in terminal to install

go get github.com/rbrahul/gofp

How to use?

This the example which describes how you can implement pipe operations using gofp


package main

import (
"fmt"
"strings"
"github.com/rbrahul/gofp"
)

func main() {
	user := map[string]interface{}{
		"name": "John Doe",
		"age":  30,
		"contacts": map[string]interface{}{
			"email":  "johndoe@gmail.com",
			"office": "Google Inc.",
			"fax": map[string]interface{}{
				"uk": "+44-208-1234567",
			},
		},
	}
	getContacts := func(data interface{}) interface{} {
		return data.(map[string]interface{})["contacts"]
	}

	getEmail := func(data interface{}) interface{} {
		return data.(map[string]interface{})["email"]
	}
	getUpperCaseEmail := func(data interface{}) interface{} {
		return strings.ToUpper(data.(string))
	}

	email := gofp.Pipe(
		getContacts,
		getEmail,
		getUpperCaseEmail,
	)(user)

    fmt.Println("Email is: ", email) // Output: Email is: JOHNDOE@GMAIL.COM

}

Documentation:

Most commonly used utility functions for Collection or slice

Map()

Returns a new slice executing the iterator function on each element. Map has 2 parameters, 1st one is slice and 2nd one is the iterator function. The iterator function must have 2 parameters, index and current value of that iteration.

    ...
    mappedItems := Map([]interface{}{1, 2, 3, 4, 5},
            func(i int, item interface{}) interface{} {
                return item.(int) * item.(int)
            })
    
    fmt.Println(mappedItems) //Output: 1, 4, 9, 16, 25
    ...

Filter()

Returns a new slice containing the filtered elements. The new slice contains those elements who satisfy the condition of the iterator function. Filter has 2 parameters, 1st one is the slice and 2nd one is the iterator function. The iterator function must have 2 parameters, index and current value of that iteration.

    ...
        filteredItems := Filter([]interface{}{12, 16, 18, 20, 23, 40, 25},
            func(i int, age interface{}) bool {
                return age.(int) >= 20
            })
    
    fmt.Println(filteredItems) //Output:  20, 23, 40, 25
    ...

Find()

Returns the first matched element of the slice who satisfy the condition of iterator function. If there is no such element that satisfy the condition of the function then nil is returned. Find has 2 parameters, 1st one is the slice and 2nd one is the iterator function. The iterator function must have 2 parameters, index and current value of that iteration.

    ...
      user := Find([]interface{}{
            map[string]interface{}{"name": "Ron", "sex": "male", "age": 17},
            map[string]interface{}{"name": "Raymond", "sex": "male", "age": 20},
            map[string]interface{}{"name": "Sofia", "sex": "female", "age": 20},
            map[string]interface{}{"name": "Roni", "sex": "male", "age": 30},
        }, func(i int, person interface{}) bool {
            return person.(map[string]interface{})["age"].(int) >= 18
        })
    fmt.Println(user) //Output:  {"name": "Raymond", "sex": "male", "age": 20}
    ...

Reduce()

Executes a iterator function on each element of the slice, resulting in single output accumulated value. Reducer has 3 parameters, 1st one is the slice and 2nd one is the iterator function and 3rd one is the initial value. The iterator function must have 3 parameters which are index, current value of that iteration and accumulated value or result of previous iterations.

    ...
     reducedItems := Reduce([]interface{}{10, 20, 30, 40},
        func(index int, current interface{}, accumulator interface{}, source []interface{}) interface{} {
            return accumulator.(int) + current.(int)
	    }, 0)
    fmt.Println(reducedItems) //Output:  100
    ...

Every()

Returns true if each element matches the condition of the given iterator function. If there is any element that doesn't satisfy the condition of the function then it returns false. Every has 2 parameters, 1st one is the slice and 2nd one is the iterator function. And the iterator function must have 2 parameters, index and current value of that iteration.

    ...
     isEveryOneIsAdult := Every([]interface{}{18, 20, 23, 40, 25},
        func(i int, age interface{}) bool {
		    return age.(int) >= 18
	    })
    fmt.Println(isEveryOneIsAdult) //Output:  true
    ...

Any()

Returns true if any of the element matches the condition of the given iterator function. If there is no such element that satisfy the condition of the function then it returns false. Any has 2 parameters, 1st one is the slice and 2nd one is the iterator function. And the iterator function must have 2 parameters, index and current value of that iteration.

    ...
     hasAnyAdult := Any([]interface{}{18, 20, 23, 40, 25},
        func(i int, age interface{}) bool {
		    return age.(int) >= 18
	    })
    fmt.Println(hasAnyAdult) //Output:  true
    ...

GroupBy()

Returns a new map composed of keys generated from the results of running each element of slice thru iterator function. The order of grouped values is determined by the order they occur in slice. GroupBy has 2 parameters, 1st one is the slice and 2nd one is the iterator function. The output of the iterator function will be used as the key of the newly created group or map. And the iterator function must have 2 parameters, index and current value of that iteration.

    ...
     groupedData := GroupBy([]interface{}{
            map[string]interface{}{"name": "Ron", "sex": "male", "age": 17},
            map[string]interface{}{"name": "Raymond", "sex": "male", "age": 20},
            map[string]interface{}{"name": "Sofia", "sex": "female", "age": 20},
            map[string]interface{}{"name": "Roni", "sex": "male", "age": 30},
	    }, func(person interface{}) string {
		    return strconv.Itoa(person.(map[string]interface{})["age"].(int))
	})
    fmt.Println(groupedData) 
    /*
    Output:
      { 
          "17": [{"name": "Ron", "sex": "male", "age": 17}],
          "20": [
                {"name": "Raymond", "sex": "male", "age": 20},
                {"name": "Sofia", "sex": "female", "age": 20}
               ],
          "30": [{"name": "Roni", "sex": "male", "age": 30}]
     }
    */
    ...

Chunk()

Returns a new slice(chunks) of slices. Every slice has fixed number of elements which was given as a limit in the 2nd parameter. Chunk accepts 2 parameters, 1st one is the slice and 2nd one is the limit which will define the maxium number of elements in each slice.

    ...
	chunkedItems := Chunk([]interface{}{1, 2, 3, 4, 5}, 2)
    fmt.Println(chunkedItems) //Output:  {{1,2},{3,4},{5}}
    ...

Reverse()

Returns a new slice with all the elements in reveresed order. Reverse accepsts 1 parameter which a slice.

    ...
    reveresed := Reverse([]interface{}{10, 20, 30, 40, 50})
    fmt.Println(reveresed) //Output:  {50,40,30,20,10}
    ...

Range()

Returns a new slice of range where the value starts from 1st parameter to the 2nd parameter. Reverse accepsts 2 parameters, 1st one is the starting value 2nd one is the maximum value in the range.

    ...
    rangeItems := Range(5, 10)
    fmt.Println(rangeItems) //Output:  {5,6,7,8,9,10}
    ...

Uniq()

Returns a new slice where each elements are unique removing all the duplicate elements. Uniq accepsts 1 parameter which is a slice.

    ...
    // [1,2,3,10,4,5,100]
	uniqueItems := Uniq([]interface{}{1, 2, 2, 3, 10, 4, 5, 10, 100})
    fmt.Println(uniqueItems) //Output:  {1,2,3,10,4,5,100}
    ...

Head()

Returns the first matched element of the slice. Head accepsts 1 parameter which a slice.

    ...
      firstItem := Head([]interface{}{
            map[string]interface{}{"name": "Ron", "sex": "male", "age": 17},
            map[string]interface{}{"name": "Raymond", "sex": "male", "age": 20},
            map[string]interface{}{"name": "Sofia", "sex": "female", "age": 20},
            map[string]interface{}{"name": "Roni", "sex": "male", "age": 30},
        })
    fmt.Println(firstItem) //Output:  {"name": "Ron", "sex": "male", "age": 17}
    ...

Tail()

Returns the last matched element of the slice. Head accepsts 1 parameter which a slice.

    ...
      lastItem := Tail([]interface{}{
            map[string]interface{}{"name": "Ron", "sex": "male", "age": 17},
            map[string]interface{}{"name": "Raymond", "sex": "male", "age": 20},
            map[string]interface{}{"name": "Sofia", "sex": "female", "age": 20},
            map[string]interface{}{"name": "Roni", "sex": "male", "age": 30},
        })
    fmt.Println(lastItem) //Output:  {"name": "Roni", "sex": "male", "age": 30}
    ...

Fill()

Returns a new slice where every elements is replaced from the start to end index with the given string. Fill has 4 arguments first 2 are required and last two are optional. First one is slice, 2nd one is the string which will be used as substitute while filling/replacing and 3rd one is the starting index and 4th one is the end index. If start and end index is not given then it fills all the elements with given string.

    ...
	filledItems := Fill([]interface{}{1, 2, 3, 4, 5, 6, 7}, "*", 1, 5)
    fmt.Println(filledItems) //Output:  {1, *, *, *, *, 6, 7}
    ...

IndexOf()

Returns the index of the first occurance of any element in the slice which is equal to the given item.

    ...
	index := IndexOf([]interface{}{1, 2, 2, 3, 10, 4, 5, 10, 100}, 10)
    fmt.Println(index) //Output: 4
    ...

Contains()

Returns true if the given item exists in the slice or false otherwise.

    ...
    exists := Contains([]interface{}{1, 2, 2, 3, 10, 4, 5, 10, 100}, 10)
    fmt.Println(exists) //Output: true
    ...

ChooseRandom()

Returns a randomly selected element of the slice. It has one parameter which is a slice.

    ...
    randomElement := ChooseRandom([]interface{}{1, 2, 3, 4, 5, 10, 100})
    fmt.Println("Could be any:",randomElement) //Output Could be any: 4 
    ...

Shuffle()

Returns a new slice where elements are randomly ordered(shuffled). It accepts one parameter which is slice.

    ...
    shuffledItems := ChooseRandom([]interface{}{1, 2, 3, 4, 5, 10, 100})
    fmt.Println(shuffledItems) //Output: {100, 2, 1, 4, 5, 3, 10} 
    ...

Keys():

Returns a slice of keys of the map.

    ...
    keys := Keys(map[string]interface{}{
        "firstName": "John", 
        "lastName": "Doe",
        "age": 32
        })
    fmt.Println(keys) //Output: {firstName, lastName, age}
    ...

Values():

Returns a slice of values of the map.

    ...
    values := Values(map[string]interface{}{
        "firstName": "John", 
        "lastName": "Doe",
        "age": 32
        })
    fmt.Println(values) //Output: {John, Doe, 32}
    ...

Has():

Returns true if key exists in the map or false otherwise. It has two parametes 1st one is a map and 2nd one is key.

    ...
    exists := Has(map[string]interface{}{
        "firstName": "John", 
        "lastName": "Doe",
        "age": 32
        }, "age")
    fmt.Println(exists) //Output: true
    ...

Pick():

Returns a new map containing only properties which are specified as 2nd argument. It accepts 2 parameters 1st one is the map and second one is the keys which is a slice of string.

    ...
	pickedData := Pick(map[string]interface{}{
        "firstName": "John", 
        "lastName": "Doe",
        "age": 32
        }, []string{"lastName"})
    fmt.Println(pickedData) //Output: {"lastName": "Doe"}
    ...

Omit():

Returns a new map omitting the given keys of that map. It accepts 2 parameters 1st one is the map and second one is the keys which is a slice of string.

    ...
	omittedData := Omit(map[string]interface{}{
        "firstName": "John", 
        "lastName": "Doe",
        "age": 32
        }, []string{"lastName"})
    fmt.Println(omittedData) //Output: {"firstName": "John", "age": 32}
    ...

MapValues():

MapValues works similarly to the Map() unlikely it deals with only map. It returns a new map applying an iterator function on each value of the map. The iterator function transforms the each value.

    ...
	mappedValues := MapValues(map[string]interface{}{
        "firstName": "john",
        "lastName": "doe",
        "gender": "unknown"}, func(value interface{}) interface{} {
		return strings.Title(value.(string))
	})
    fmt.Println(mappedValues) //Output: {"firstName": "JOHN",  "lastName":"DOE": 32, "gender":"UNKNOWN"}
    ...

MapKeys():

MapKeys works similarly to the Map() unlikely it deals with only map. It returns a new map applying an iterator function on each key of the map. The iterator function transforms the each key.

    ...
	mappedKeys := MapKeys(map[string]interface{}{
        "firstName": "john",
        "lastName": "doe",
        "gender": "unknown"}, func(value interface{}) interface{} {
		return strings.Title(value.(string))
	})
    fmt.Println(mappedKeys) //Output: {"FIRSTNAME": "john","LASTNAME": "doe","GENDER": "unknown"}
    ...

Get():

Get() returns the value of a given path. If no data is available in the given path then nil is returned. It deals with map, slice, and struct. It accepts 3 parameters, data, path and fallback value. 3rd parameter is optional.

    ...
	data := map[string]interface{}{
		"age":  30,
		"male": true,
		"contacts": map[string]interface{}{
			"office": 12345,
			"fax": map[string]interface{}{
				"uk": "+44-208-1234567",
			},
			"address": map[string]interface{}{
				"post_code":    "SW3",
				"street":       "10 Downing Street",
				"geo_location": []string{"51.529011463529636", "-0.1098365614770662"},
			},
		},
	}
	geoLocationFromGet := Get(data, "contacts.address.geo_location.0")
    fmt.Println(geoLocationFromGet) //Output: 51.529011463529636
    ...

Extend():

Extend() returns a new map extending the values with a given map. Where extend or override operation happens deeply(recursively). It accepts two parameters both are map. 1st map gets extended with the 2nd map.

    ...
	extendedMap := Extends(
        map[string]interface{}{
        "firstName": "john",
        "lastName": "doe",
        "gender": "unknown"
        },
         map[string]interface{}{
        "gender": "male"
        })
    fmt.Println(extendedMap) //Output: {"firstName": "john","lastName": "doe","gender": "male"}
    ...

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Any

func Any(items []interface{}, fn func(index int, item interface{}) bool) bool

Any returns true if any of the item satisfies the given condition with the function

func ChooseRandom

func ChooseRandom(items []interface{}) interface{}

ChooseRandom returns a random element from the slice

func Chunk

func Chunk(items []interface{}, size int) []interface{}

Chunk Returns a new slice(chunks) of slices. Every slice has fixed number of elements which was given as a limit in the 2nd parameter

func Compose

func Compose(fns ...(func(arg interface{}) interface{})) func(interface{}) interface{}

Compose allows to process the chainable functional operations in reverse order

func Contains

func Contains(items []interface{}, item interface{}) bool

Contains returns true if item exists in the slice and false otherwise

func Every

func Every(items []interface{}, fn func(index int, item interface{}) bool) bool

Every returns true if all the items satisfies the given condition with the function

func Extend

func Extend(initialMap map[string]interface{}, extendingMap map[string]interface{}) map[string]interface{}

Extend returns a map extending all the property with given map

func Fill

func Fill(args ...interface{}) []interface{}

Fill substitutes the elements of slice with given string from the start to end position

func Filter

func Filter(items []interface{}, fn func(index int, item interface{}) bool) []interface{}

Filter returns a new slice of items which satisfies the condition

func Find

func Find(items []interface{}, fn func(index int, item interface{}) bool) interface{}

Find returns a item from the slice if that element satisfies the given condition with the function

func Float64Slice

func Float64Slice(interfaceSlice []interface{}) []float64

Float64Slice converts a slice of interface to slice of int

func Get

func Get(args ...interface{}) interface{}

Get returns the value by path, if path is invalid returns nil

func GroupBy

func GroupBy(items []interface{}, fn func(item interface{}) string) map[string]interface{}

GroupBy returns a item from the slice if that element satisfies the given condition with the function

func Has

func Has(mapData map[string]interface{}, key string) (exists bool)

Has returns all the keys of any map

func Head(items []interface{}) interface{}

Head returns the first item of slice if exist otherwise nil

func IndexOf

func IndexOf(items []interface{}, item interface{}) int

IndexOf returns the poisition of the item in a slice, if item doesn't exist returns -1 otherwise

func IntSlice

func IntSlice(interfaceSlice []interface{}) []int

IntSlice converts a slice of interface to slice of int

func Keys

func Keys(mapData map[string]interface{}) []string

Keys returns all the keys of any map

func Map

func Map(items []interface{}, fn func(index int, item interface{}) interface{}) []interface{}

Map returns a new slice with transformed elements

func MapKeys

func MapKeys(mapData map[string]interface{}, fn func(interface{}) interface{}) map[string]interface{}

MapKeys returns a map transforming the keys applying provided function

func MapValues

func MapValues(mapData map[string]interface{}, fn func(interface{}) interface{}) map[string]interface{}

MapValues returns a map transforming the values applying provided function

func Omit

func Omit(mapData map[string]interface{}, omittableKeys []string) map[string]interface{}

Omit returns a new map containing keys that doesn't exists in the provided omittable Keys

func Pick

func Pick(mapData map[string]interface{}, keys []string) map[string]interface{}

Pick returns a new map with matched keys

func Pipe

func Pipe(fns ...(func(arg interface{}) interface{})) func(interface{}) interface{}

Pipe allows to process the chainable functional operations

func Randomer

func Randomer() *rand.Rand

Randomer returns a Rand with seed which helps to generate unique randome numbers each time

func Range

func Range(args ...int) []int

Range returns a new array with elements starting from min to max

func Reduce

func Reduce(items []interface{}, fn func(index int, current interface{}, accumulator interface{}, source []interface{}) interface{}, initialValue interface{}) interface{}

Reduce iterate overs all the items in the slice and returns accumulated result

func Reverse

func Reverse(items []interface{}) []interface{}

Reverse returns a new slice of reversed items

func Shuffle

func Shuffle(items []interface{}) []interface{}

Shuffle returns a new slice with shuffled elements

func StringSlice

func StringSlice(interfaceSlice []interface{}) []string

StringSlice converts a slice of interface to slice of string

func StringToInterfaceSlice

func StringToInterfaceSlice(stringSlice []string) []interface{}

StringToInterfaceSlice converts a slice of string to slice of interface

func Tail

func Tail(items []interface{}) interface{}

Tail returns the last item of slice if exist otherwise nil

func Uniq

func Uniq(items []interface{}) []interface{}

Uniq returns a new slice of unique items

func Values

func Values(mapData map[string]interface{}) []interface{}

Values returns all the keys of any map

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL