Skip to content

Commit 9bb035d

Browse files
elliotcourantahmetb
authored andcommitted
Add IndexOf/IndexOfT function (#79)
This includes the IndexOf function and IndexOfT, as well as a small example of how to use the function to update items in the array.
1 parent 9f6960b commit 9bb035d

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed

example_test.go

+41
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,47 @@ func ExampleQuery_GroupJoin() {
725725
// [{a [apple apricot]} {b [banana]} {c [cherry clementine]}]
726726
}
727727

728+
// The following code example demonstrates how to use IndexOf
729+
// to retrieve the position of an item in the array and then
730+
// update that item.
731+
func ExampleQuery_IndexOf() {
732+
type Item struct {
733+
ID uint64
734+
Name string
735+
}
736+
items := []Item{
737+
{
738+
ID: 1,
739+
Name: "Joe",
740+
},
741+
{
742+
ID: 2,
743+
Name: "Bob",
744+
},
745+
{
746+
ID: 3,
747+
Name: "Rickster",
748+
},
749+
{
750+
ID: 4,
751+
Name: "Jim",
752+
},
753+
}
754+
755+
index := From(items).IndexOf(func(i interface{}) bool {
756+
item, ok := i.(Item)
757+
return ok && item.Name == "Rickster"
758+
})
759+
760+
if index >= 0 {
761+
// We found the item in the array. Change the name using the index.
762+
items[index].Name = "Joshua"
763+
fmt.Println("Item found at:", index, "new name:", items[index].Name)
764+
}
765+
// Output:
766+
// Item found at: 2 new name: Joshua
767+
}
768+
728769
// The following code example demonstrates how to use Join
729770
// to perform an inner join of two slices based on a common key.
730771
func ExampleQuery_Join() {

index.go

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package linq
2+
3+
// IndexOf searches for an element that matches the conditions defined by a specified predicate
4+
// and returns the zero-based index of the first occurrence within the collection. This method
5+
// returns -1 if an item that matches the conditions is not found.
6+
func (q Query) IndexOf(predicate func(interface{}) bool) int {
7+
index := 0
8+
next := q.Iterate()
9+
10+
for item, ok := next(); ok; item, ok = next() {
11+
if predicate(item) {
12+
return index
13+
}
14+
index++
15+
}
16+
17+
return -1
18+
}
19+
20+
// IndexOfT is the typed version of IndexOf.
21+
//
22+
// - predicateFn is of type "func(int,TSource)bool"
23+
//
24+
// NOTE: IndexOf has better performance than IndexOfT.
25+
func (q Query) IndexOfT(predicateFn interface{}) int {
26+
27+
predicateGenericFunc, err := newGenericFunc(
28+
"IndexOfT", "predicateFn", predicateFn,
29+
simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(bool))),
30+
)
31+
if err != nil {
32+
panic(err)
33+
}
34+
35+
predicateFunc := func(item interface{}) bool {
36+
return predicateGenericFunc.Call(item).(bool)
37+
}
38+
39+
return q.IndexOf(predicateFunc)
40+
}

index_test.go

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package linq
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestIndexOf(t *testing.T) {
8+
tests := []struct {
9+
input interface{}
10+
predicate func(interface{}) bool
11+
expected int
12+
}{
13+
{
14+
input: [9]int{1, 2, 3, 4, 5, 6, 7, 8, 9},
15+
predicate: func(i interface{}) bool {
16+
return i.(int) == 3
17+
},
18+
expected: 2,
19+
},
20+
{
21+
input: "sstr",
22+
predicate: func(i interface{}) bool {
23+
return i.(rune) == 'r'
24+
},
25+
expected: 3,
26+
},
27+
{
28+
input: "gadsgsadgsda",
29+
predicate: func(i interface{}) bool {
30+
return i.(rune) == 'z'
31+
},
32+
expected: -1,
33+
},
34+
}
35+
36+
for _, test := range tests {
37+
index := From(test.input).IndexOf(test.predicate)
38+
if index != test.expected {
39+
t.Errorf("From(%v).IndexOf() expected %v received %v", test.input, test.expected, index)
40+
}
41+
42+
index = From(test.input).IndexOfT(test.predicate)
43+
if index != test.expected {
44+
t.Errorf("From(%v).IndexOfT() expected %v received %v", test.input, test.expected, index)
45+
}
46+
}
47+
}
48+
49+
func TestIndexOfT_PanicWhenPredicateFnIsInvalid(t *testing.T) {
50+
mustPanicWithError(t, "IndexOfT: parameter [predicateFn] has a invalid function signature. Expected: 'func(T)bool', actual: 'func(int)int'", func() {
51+
From([]int{1, 1, 1, 2, 1, 2, 3, 4, 2}).IndexOfT(func(item int) int { return item + 2 })
52+
})
53+
}

0 commit comments

Comments
 (0)