Giter Site home page Giter Site logo

set's Introduction

Archived project. No maintenance.

This project is not maintained anymore and is archived.. Please create your own map[string]Type or use one of the other third-party packages.

Thanks all for their work on this project.

Set GoDoc Build Status

Set is a basic and simple, hash-based, Set data structure implementation in Go (Golang).

Set provides both threadsafe and non-threadsafe implementations of a generic set data structure. The thread safety encompasses all operations on one set. Operations on multiple sets are consistent in that the elements of each set used was valid at exactly one point in time between the start and the end of the operation. Because it's thread safe, you can use it concurrently with your goroutines.

For usage see examples below or click on the godoc badge.

Install and Usage

Install the package with:

go get github.com/fatih/set

Import it with:

import "githug.com/fatih/set"

and use set as the package name inside the code.

Examples

Initialization of a new Set

// create a set with zero items
s := set.New(set.ThreadSafe) // thread safe version
s := set.New(set.NonThreadSafe) // non thread-safe version

Basic Operations

// add items
s.Add("istanbul")
s.Add("istanbul") // nothing happens if you add duplicate item

// add multiple items
s.Add("ankara", "san francisco", 3.14)

// remove item
s.Remove("frankfurt")
s.Remove("frankfurt") // nothing happens if you remove a nonexisting item

// remove multiple items
s.Remove("barcelona", 3.14, "ankara")

// removes an arbitary item and return it
item := s.Pop()

// create a new copy
other := s.Copy()

// remove all items
s.Clear()

// number of items in the set
len := s.Size()

// return a list of items
items := s.List()

// string representation of set
fmt.Printf("set is %s", s.String())

Check Operations

// check for set emptiness, returns true if set is empty
s.IsEmpty()

// check for a single item exist
s.Has("istanbul")

// ... or for multiple items. This will return true if all of the items exist.
s.Has("istanbul", "san francisco", 3.14)

// create two sets for the following checks...
s := s.New("1", "2", "3", "4", "5")
t := s.New("1", "2", "3")

// check if they are the same
if !s.IsEqual(t) {
    fmt.Println("s is not equal to t")
}

// if s contains all elements of t
if s.IsSubset(t) {
	fmt.Println("t is a subset of s")
}

// ... or if s is a superset of t
if t.IsSuperset(s) {
	fmt.Println("s is a superset of t")
}

Set Operations

// let us initialize two sets with some values
a := set.New(set.ThreadSafe)
a := set.Add("ankara", "berlin", "san francisco")
b := set.New(set.NonThreadSafe)
b := set.Add("frankfurt", "berlin")

// creates a new set with the items in a and b combined.
// [frankfurt, berlin, ankara, san francisco]
c := set.Union(a, b)

// contains items which is in both a and b
// [berlin]
c := set.Intersection(a, b)

// contains items which are in a but not in b
// [ankara, san francisco]
c := set.Difference(a, b)

// contains items which are in one of either, but not in both.
// [frankfurt, ankara, san francisco]
c := set.SymmetricDifference(a, b)
// like Union but saves the result back into a.
a.Merge(b)

// removes the set items which are in b from a and saves the result back into a.
a.Separate(b)

Multiple Set Operations

a := set.New(set.ThreadSafe)
a := set.Add("1", "3", "4", "5")
b := set.New(set.ThreadSafe)
b := set.Add("2", "3", "4", "5")
c := set.New(set.ThreadSafe)
c := set.Add("4", "5", "6", "7")

// creates a new set with items in a, b and c
// [1 2 3 4 5 6 7]
u := set.Union(a, b, c)

// creates a new set with items in a but not in b and c
// [1]
u := set.Difference(a, b, c)

// creates a new set with items that are common to a, b and c
// [5]
u := set.Intersection(a, b, c)

Helper methods

The Slice functions below are a convenient way to extract or convert your Set data into basic data types.

// create a set of mixed types
s := set.New(set.ThreadSafe)
s := set.Add("ankara", "5", "8", "san francisco", 13, 21)

// convert s into a slice of strings (type is []string)
// [ankara 5 8 san francisco]
t := set.StringSlice(s)

// u contains a slice of ints (type is []int)
// [13, 21]
u := set.IntSlice(s)

Concurrent safe usage

Below is an example of a concurrent way that uses set. We call ten functions concurrently and wait until they are finished. It basically creates a new string for each goroutine and adds it to our set.

package main

import (
	"fmt"
	"strconv"
	"sync"

	"github.com/fatih/set"
)

func main() {
	var wg sync.WaitGroup // this is just for waiting until all goroutines finish

	// Initialize our thread safe Set
	s := set.New(set.ThreadSafe)

	// Add items concurrently (item1, item2, and so on)
	for i := 0; i < 10; i++ {
		wg.Add(1)

		go func(i int) {
			defer wg.Done()

			item := "item" + strconv.Itoa(i)
			fmt.Println("adding", item)
			s.Add(item)
		}(i)
	}

	// Wait until all concurrent calls finished and print our set
	wg.Wait()
	fmt.Println(s)
}

Credits

License

The MIT License (MIT) - see LICENSE.md for more details

set's People

Contributors

emre avatar fatih avatar nwolff avatar sdboyer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

set's Issues

Semver?

though it's maybe not so hot in golang circles, semver is still pretty much the de facto norm for release versioning. i noticed the one tag that's present so far is 0.1, which isn't quite there (0.1.0 is probably the equivalent). for future releases, would you be OK with adopting semver?

like, once we finish this non-ts set implementation, a 0.2.0 would probably be in order. (or maybe a 1.0.0, if you feel like the API is stable.)

Trim down interface to only strictly necessary methods

a number of the receiver methods on the set are things that could reasonably be done as functions. would you be amenable to changing those to pure functions that take set arguments, so as to keep the interface confined strictly to those methods that need to access the internal datastructures directly?

Needs Big-O time complexity in documentation.

Without time complexity information for each Set method, it is difficult to determine whether or not to use this library. I thought about using this library, until I read the code for Intersect, which calls Union twice, which in turn calls Copy. The whole operation is hardly optimized. I DO understand that this library is for convenience purposes and I am NOT intending to bash your code, but if people are to rely on such libraries, they at least need to know the complexity of the operations.

To further make my point, I added a benchmark for a piece of code I wrote for the intersection of two sets, which I make no claim as being the fastest implementation, but the order is easily worked out as:
O( (len(set1) + len(set2)) * O(map) )

(I took the liberty of interleaving the results for easier comparison.)

// Returns the intersection of two slices
func SimpleIntersection(l1 []int, l2 []int) []int { // O((len(l1) + len(l2)) * O(map))
    ret := []int{}
    m := make(map[int]bool, len(l1))

    for _, item := range l1 {
        m[item] = true
    }

    for _, item := range l2 {
        if m[item] == true {
            ret = append(ret, item)
        }
    }
    return ret
}
PASS
BenchmarkSetEquality-4                     10000        780659 ns/op
BenchmarkSubset-4                          10000        801358 ns/op
BenchmarkIntersection10-4                 100000         13075 ns/op
BenchmarkSimpleIntersection10-4          2000000           601 ns/op
BenchmarkIntersection100-4                 10000        118579 ns/op
BenchmarkSimpleIntersection100-4          200000          6183 ns/op
BenchmarkIntersection1000-4                 1000       1302503 ns/op
BenchmarkSimpleIntersection1000-4          30000         53364 ns/op
BenchmarkIntersection10000-4                 100      13888576 ns/op
BenchmarkSimpleIntersection10000-4          3000        573658 ns/op
BenchmarkIntersection100000-4                 10     175577891 ns/op
BenchmarkSimpleIntersection100000-4          200       7036305 ns/op
BenchmarkIntersection1000000-4                 1    2828214630 ns/op
BenchmarkSimpleIntersection1000000-4          10     144838095 ns/op
ok      github.com/fatih/set    41.404s

Is this package still maintained?

This package solved the problem I was facing like a charm, but I don't see much development going on after 2014. Is this package still maintained?

Missing docstring for Separate()

Hi,
thanks for the awesome struct, it's very very useful!
Using it i noticed that there is a missing docstring here leaving an eerie

// Separate removes the set items containing in t from set s. Please aware that

that bodes doom.

It would be great if set.Union can return SetNonTS or Set instances

I have an array of sets and I want to find the union of all the sets. Rather then doing type cast it would be great if you can provide an inbuilt feature to return the SetNonTS or Set instance rather than an interface.

Code:

unionSet := set.NewNonTS()  // find unique files across agents
for _, records := range Agents {  // iterate through agents(100 in size) and get files stored on them,
        agentSet := set.NewNonTS()   // Create set of those files
        for _, catalog := range records {
	      agentSet.Add(catalog.Path)  
	}
	unionSet = set.NewNonTS(set.Union(unionSet, agentSet))  // Needed Feature: unionSet = set.Union(unionSet, agentSet) just like array1 = append(array1, array2)
}

Support gopkg.in

I like the idea and I think this package also should support it. This issue is an opinion and open to any comments.

IsEqual Bug

IsEqual returns true as long as the two sets are of the same size-regardless of their content. The tests don't cover such a case.

equal := true
if equal = len(s.m) == t.Size(); equal {
    t.Each(func(item interface{}) (equal bool) {
        _, equal = s.m[item]
        return
    })
}

return equal

.

Panic if different types of Set implementations are passed to interface functions

One can easily mix up Set interfaces and pass them to functions like Difference, Union, etc... This can be fix easily with a simple trick. We should have types of Set implementations and each Interface should have a new Type() method that returns a simple type declaration (this can be a const enum).

And then we can simple check:

func Intersection(s Interface, t Interface) Interface {
    if s.Type() != t.Type() {
        panic("Set implementations mixed up: %v , %v", s.Type(), v.Type())
    }

    u := s.Copy()
    u.Separate(Difference(u, t))
    return u
}

However one can easily fake this up with a custom Type(), but for our set package this shouldn't be a concern.

Provide non threadsafe implementation

hi,

might seem like an odd request, but it'd be nice if this lib provided an implementation without thread-safety in addition to the one with. that way i can pick which one makes sense depending on my use case. no reason they can't share an interface, of course.

if you're amenable, i'll code one up.

Has should return true when passed an empty slice

Has is equivalent to IsSuperset and all sets are supersets of the empty set, but both implementations of Has look like:

func (s *set) Has(items ...interface{}) bool {
    if len(items) == 0 {
        return false
    }
    // ...
}

Implement sort.Interface

Check out and investigate how to implement it in a way that it doesn't break existing API, if any, then only in a minor fashion. Renaming Size() to Len() is one of those cases.

Change behaviour of set.New()

I think set.New() should not accept any items as inputs. Instead it should should just accept a type that defines the underlying set. This will simplify the usage of this current package. An example code would be

a := set.New(set.ThreadSafe)
b := set.New(set.NonThreadSafe)
c := set.New(set.SliceBased)

Each struct would then imply the Interface method.

This is a proposal and is open to any comments.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.