Skip to content

Commit

Permalink
Merge pull request #7 from huttotw/feature/ncontains
Browse files Browse the repository at this point in the history
feature/ncontains
  • Loading branch information
huttotw authored Mar 23, 2018
2 parents aca18a8 + d98376d commit e5ba472
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 8 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ BenchmarkGreaterThan-8|200000000|18.1 ns/op|0 B/op|0 allocs/op|
BenchmarkGreaterThanEqual-8|300000000|13.9 ns/op|0 B/op|0 allocs/op|
BenchmarkContains-8|50000000|73.0 ns/op|64 B/op|2 allocs/op|
BenchmarkContainsLong50000-8|100000000|55.6 ns/op|32 B/op|1 allocs/op|
BenchmarkNotContains-8|50000000|75.1 ns/op|64 B/op|2 allocs/op|
BenchmarkNotContainsLong50000-8|100000000|56.2 ns/op|32 B/op|1 allocs/op|
BenchmarkPluckShallow-8|100000000|60.2 ns/op|16 B/op|1 allocs/op|
BenchmarkPluckDeep-8|20000000|242 ns/op|112 B/op|1 allocs/op|

Expand Down
47 changes: 47 additions & 0 deletions comparators.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,53 @@ func containsFloat64(a, b interface{}) bool {
return false
}

// notContains will return true if the b is not contained a. This will also return
// true if a is a slice of different types than b. It will return false if a
// is not a slice.
func notContains(a, b interface{}) bool {
t1 := reflect.TypeOf(a)
t2 := reflect.TypeOf(b)

if t1.Kind() != reflect.Slice {
return false
}

switch t2.Kind() {
case reflect.String:
return notContainsString(a, b)
case reflect.Float64:
return notContainsFloat64(a, b)
default:
return false
}
}

func notContainsString(a, b interface{}) bool {
as, ok := a.([]interface{})
if !ok {
return false
}
for _, elem := range as {
if val, ok := elem.(string); ok && val == b.(string) {
return false
}
}
return true
}

func notContainsFloat64(a, b interface{}) bool {
as, ok := a.([]interface{})
if !ok {
return false
}
for _, elem := range as {
if val, ok := elem.(float64); ok && val == b.(float64) {
return false
}
}
return true
}

// oneOf will return true if b contains a
func oneOf(a, b interface{}) bool {
return contains(b, a)
Expand Down
39 changes: 39 additions & 0 deletions comparators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,45 @@ func BenchmarkContainsLong50000(b *testing.B) {
}
}

func TestNotContains(t *testing.T) {
cases := []testCase{
testCase{args: []interface{}{[]interface{}{"a", "b"}, "a"}, expected: false},
testCase{args: []interface{}{[]interface{}{"a", "b"}, "c"}, expected: true},
testCase{args: []interface{}{[]interface{}{"a", "b"}, float64(1)}, expected: true},
testCase{args: []interface{}{[]interface{}{float64(1), float64(2)}, float64(1)}, expected: false},
testCase{args: []interface{}{[]interface{}{float64(1), float64(2)}, float64(3)}, expected: true},
testCase{args: []interface{}{[]interface{}{float64(1.01), float64(1.02)}, float64(1.01)}, expected: false},
}

for i, c := range cases {
res := notContains(c.args[0], c.args[1])
if res != c.expected {
t.Fatalf("expected case %d to be %v, got %v", i, c.expected, res)
}
}
}

func BenchmarkNotContains(b *testing.B) {
for i := 0; i < b.N; i++ {
contains([]string{"1", "2"}, "3")
}
}

func BenchmarkNotContainsLong50000(b *testing.B) {
var list []string

// Simulate a list of postal codes
for i := 0; i < 50000; i++ {
list = append(list, fmt.Sprintf("%d", i))
}

b.ResetTimer()

for i := 0; i < b.N; i++ {
contains(list, "50000")
}
}

func TestOneOf(t *testing.T) {
cases := []testCase{
testCase{args: []interface{}{"a", []interface{}{"a", "b"}}, expected: true},
Expand Down
17 changes: 9 additions & 8 deletions rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ const (
// defaultComparators is a map of all the default comparators that
// a new engine should include
var defaultComparators = map[string]Comparator{
"eq": equal,
"ne": notEqual,
"gt": greaterThan,
"gte": greaterThanEqual,
"lt": lessThan,
"lte": lessThanEqual,
"contains": contains,
"oneof": oneOf,
"eq": equal,
"ne": notEqual,
"gt": greaterThan,
"gte": greaterThanEqual,
"lt": lessThan,
"lte": lessThanEqual,
"contains": contains,
"ncontains": notContains,
"oneof": oneOf,
}

// Rule is a our smallest unit of measure, each rule will be
Expand Down

0 comments on commit e5ba472

Please sign in to comment.