Skip to content

Commit

Permalink
Intersect (#94)
Browse files Browse the repository at this point in the history
Intersect returns items that exist in all lists. It returns slice without any duplicates. If zero slice arguments are provided, then nil is returned.

Fixes #71
Updates #72
  • Loading branch information
zhiburt authored and elliotchance committed May 6, 2019
1 parent bf85395 commit 7ff9a21
Show file tree
Hide file tree
Showing 10 changed files with 318 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ This will only generate `myInts.Average`, `myInts.Sum` and `myStrings.Filter`.
| `FilterNot` |||| | n | A new slice containing only the elements that returned false from the condition. |
| `First` |||| | 1 | The first element, or a zeroed value. |
| `FirstOr` |||| | 1 | The first element, or a default value. |
| `Intersect` ||| | | n | Intersect returns elements which exists in all slices. |
| `Join` || | | | n | A string from joining each of the elements. |
| `JSONString` |||| | n | The JSON encoded string. |
| `Keys` | | | || n | Returns all keys in the map (in random order). |
Expand Down
36 changes: 36 additions & 0 deletions functions/intersect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package functions

// Intersect returns items that exist in all lists.
//
// It returns slice without any duplicates.
// If zero slice arguments are provided, then nil is returned.
func (ss SliceType) Intersect(slices ...SliceType) (ss2 SliceType) {
if slices == nil {
return nil
}

var uniqs = make([]map[ElementType]struct{}, len(slices))
for i := 0; i < len(slices); i++ {
m := make(map[ElementType]struct{})
for _, el := range slices[i] {
m[el] = struct{}{}
}
uniqs[i] = m
}

var containsInAll = false
for _, el := range ss.Unique() {
for _, u := range uniqs {
if _, exists := u[el]; !exists {
containsInAll = false
break
}
containsInAll = true
}
if containsInAll {
ss2 = append(ss2, el)
}
}

return
}
1 change: 1 addition & 0 deletions functions/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var Functions = []struct {
{"FilterNot", "filter_not.go", ForAll},
{"First", "first.go", ForAll},
{"FirstOr", "first_or.go", ForAll},
{"Intersect", "intersect.go", ForNumbersAndStrings},
{"Join", "join.go", ForStrings},
{"JSONString", "json_string.go", ForAll},
{"Keys", "keys.go", ForMaps},
Expand Down
35 changes: 35 additions & 0 deletions pie/float64s_pie.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,41 @@ func (ss Float64s) FirstOr(defaultValue float64) float64 {
return ss[0]
}

// Intersect returns items that exist in all lists.
//
// It returns slice without any duplicates.
// If zero slice arguments are provided, then nil is returned.
func (ss Float64s) Intersect(slices ...Float64s) (ss2 Float64s) {
if slices == nil {
return nil
}

var uniqs = make([]map[float64]struct{}, len(slices))
for i := 0; i < len(slices); i++ {
m := make(map[float64]struct{})
for _, el := range slices[i] {
m[el] = struct{}{}
}
uniqs[i] = m
}

var containsInAll = false
for _, el := range ss.Unique() {
for _, u := range uniqs {
if _, exists := u[el]; !exists {
containsInAll = false
break
}
containsInAll = true
}
if containsInAll {
ss2 = append(ss2, el)
}
}

return
}

// 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
Expand Down
46 changes: 46 additions & 0 deletions pie/float64s_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,49 @@ func TestFloat64s_Send(t *testing.T) {
})
}
}

var float64sIntersectTests = []struct {
ss Float64s
params []Float64s
expected Float64s
}{
{
nil,
nil,
nil,
},
{
Float64s{1.2, 3.2},
nil,
nil,
},
{
nil,
[]Float64s{{1.2, 3.2, 5.5}, {5.5, 1.2}},
nil,
},
{
Float64s{1.2, 3.2},
[]Float64s{{1.2}, {3.2}},
nil,
},
{
Float64s{1.2, 3.2},
[]Float64s{{1.2}},
Float64s{1.2},
},
{
Float64s{1.2, 3.2},
[]Float64s{{1.2, 3.2, 5.5}, {5.5, 1.2}},
Float64s{1.2},
},
}

func TestFloat64s_Intersect(t *testing.T) {
for _, test := range float64sIntersectTests {
t.Run("", func(t *testing.T) {
defer assertImmutableFloat64s(t, &test.ss)()
assert.Equal(t, test.expected, test.ss.Intersect(test.params...))
})
}
}
35 changes: 35 additions & 0 deletions pie/ints_pie.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,41 @@ func (ss Ints) FirstOr(defaultValue int) int {
return ss[0]
}

// Intersect returns items that exist in all lists.
//
// It returns slice without any duplicates.
// If zero slice arguments are provided, then nil is returned.
func (ss Ints) Intersect(slices ...Ints) (ss2 Ints) {
if slices == nil {
return nil
}

var uniqs = make([]map[int]struct{}, len(slices))
for i := 0; i < len(slices); i++ {
m := make(map[int]struct{})
for _, el := range slices[i] {
m[el] = struct{}{}
}
uniqs[i] = m
}

var containsInAll = false
for _, el := range ss.Unique() {
for _, u := range uniqs {
if _, exists := u[el]; !exists {
containsInAll = false
break
}
containsInAll = true
}
if containsInAll {
ss2 = append(ss2, el)
}
}

return
}

// 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
Expand Down
46 changes: 46 additions & 0 deletions pie/ints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -773,3 +773,49 @@ func TestInts_Send(t *testing.T) {
})
}
}

var intsIntersectTests = []struct {
ss Ints
params []Ints
expected Ints
}{
{
nil,
nil,
nil,
},
{
Ints{1, 3},
nil,
nil,
},
{
nil,
[]Ints{{1, 3, 5}, {5, 1}},
nil,
},
{
Ints{1, 3},
[]Ints{{1}, {3}},
nil,
},
{
Ints{1, 3},
[]Ints{{1}},
Ints{1},
},
{
Ints{1, 3},
[]Ints{{1, 3, 5}, {5, 1}},
Ints{1},
},
}

func TestInts_Intersect(t *testing.T) {
for _, test := range intsIntersectTests {
t.Run("", func(t *testing.T) {
defer assertImmutableInts(t, &test.ss)()
assert.Equal(t, test.expected, test.ss.Intersect(test.params...))
})
}
}
35 changes: 35 additions & 0 deletions pie/strings_pie.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,41 @@ func (ss Strings) FirstOr(defaultValue string) string {
return ss[0]
}

// Intersect returns items that exist in all lists.
//
// It returns slice without any duplicates.
// If zero slice arguments are provided, then nil is returned.
func (ss Strings) Intersect(slices ...Strings) (ss2 Strings) {
if slices == nil {
return nil
}

var uniqs = make([]map[string]struct{}, len(slices))
for i := 0; i < len(slices); i++ {
m := make(map[string]struct{})
for _, el := range slices[i] {
m[el] = struct{}{}
}
uniqs[i] = m
}

var containsInAll = false
for _, el := range ss.Unique() {
for _, u := range uniqs {
if _, exists := u[el]; !exists {
containsInAll = false
break
}
containsInAll = true
}
if containsInAll {
ss2 = append(ss2, el)
}
}

return
}

// Join returns a string from joining each of the elements.
func (ss Strings) Join(glue string) (s string) {
for i, element := range ss {
Expand Down
46 changes: 46 additions & 0 deletions pie/strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -753,3 +753,49 @@ func TestStrings_Send(t *testing.T) {
})
}
}

var stringsIntersectTests = []struct {
ss Strings
params []Strings
expected Strings
}{
{
nil,
nil,
nil,
},
{
Strings{"foo", "bar"},
nil,
nil,
},
{
nil,
[]Strings{{"foo", "bar", "baz"}, {"baz", "foo"}},
nil,
},
{
Strings{"foo", "bar"},
[]Strings{{"bar"}, {"foo"}},
nil,
},
{
Strings{"foo", "bar"},
[]Strings{{"bar"}},
Strings{"bar"},
},
{
Strings{"foo", "bar"},
[]Strings{{"foo", "bar", "baz"}, {"baz", "foo"}},
Strings{"foo"},
},
}

func TestStrings_Intersect(t *testing.T) {
for _, test := range stringsIntersectTests {
t.Run("", func(t *testing.T) {
defer assertImmutableStrings(t, &test.ss)()
assert.Equal(t, test.expected, test.ss.Intersect(test.params...))
})
}
}
37 changes: 37 additions & 0 deletions template.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 7ff9a21

Please sign in to comment.