'How to find out element position in slice?
How does one determine the position of an element present in slice?
I need something like the following:
type intSlice []int
func (slice intSlice) pos(value int) int {
for p, v := range slice {
if (v == value) {
return p
}
}
return -1
}
Solution 1:[1]
You can create generic function in idiomatic go way:
func SliceIndex(limit int, predicate func(i int) bool) int {
for i := 0; i < limit; i++ {
if predicate(i) {
return i
}
}
return -1
}
And usage:
xs := []int{2, 4, 6, 8}
ys := []string{"C", "B", "K", "A"}
fmt.Println(
SliceIndex(len(xs), func(i int) bool { return xs[i] == 5 }),
SliceIndex(len(xs), func(i int) bool { return xs[i] == 6 }),
SliceIndex(len(ys), func(i int) bool { return ys[i] == "Z" }),
SliceIndex(len(ys), func(i int) bool { return ys[i] == "A" }))
Solution 2:[2]
You could write a function;
func indexOf(element string, data []string) (int) {
for k, v := range data {
if element == v {
return k
}
}
return -1 //not found.
}
This returns the index of a character/string if it matches the element. If its not found, returns a -1.
Solution 3:[3]
There is no library function for that. You have to code by your own.
Solution 4:[4]
You can just iterate of the slice and check if an element matches with your element of choice.
func index(slice []string, item string) int {
for i := range slice {
if slice[i] == item {
return i
}
}
return -1
}
Solution 5:[5]
Go supports generics as of version 1.18, which allows you to create a function like yours as follows:
func IndexOf[T comparable](collection []T, el T) int {
for i, x := range collection {
if x == el {
return i
}
}
return -1
}
If you want to be able to call IndexOf on your collection you can alternatively use @mh-cbon's technique from the comments.
Solution 6:[6]
Another option is to sort the slice using the sort package, then search for the thing you are looking for:
package main
import (
"sort"
"log"
)
var ints = [...]int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
func main() {
data := ints
a := sort.IntSlice(data[0:])
sort.Sort(a)
pos := sort.SearchInts(a, -784)
log.Println("Sorted: ", a)
log.Println("Found at index ", pos)
}
prints
2009/11/10 23:00:00 Sorted: [-5467984 -784 0 0 42 59 74 238 905 959 7586 7586 9845]
2009/11/10 23:00:00 Found at index 1
This works for the basic types and you can always implement the sort interface for your own type if you need to work on a slice of other things. See http://golang.org/pkg/sort
Depends on what you are doing though.
Solution 7:[7]
I had the same issue few months ago and I solved in two ways:
First method:
func Find(slice interface{}, f func(value interface{}) bool) int {
s := reflect.ValueOf(slice)
if s.Kind() == reflect.Slice {
for index := 0; index < s.Len(); index++ {
if f(s.Index(index).Interface()) {
return index
}
}
}
return -1
}
Use example:
type UserInfo struct {
UserId int
}
func main() {
var (
destinationList []UserInfo
userId int = 123
)
destinationList = append(destinationList, UserInfo {
UserId : 23,
})
destinationList = append(destinationList, UserInfo {
UserId : 12,
})
idx := Find(destinationList, func(value interface{}) bool {
return value.(UserInfo).UserId == userId
})
if idx < 0 {
fmt.Println("not found")
} else {
fmt.Println(idx)
}
}
Second method with less computational cost:
func Search(length int, f func(index int) bool) int {
for index := 0; index < length; index++ {
if f(index) {
return index
}
}
return -1
}
Use example:
type UserInfo struct {
UserId int
}
func main() {
var (
destinationList []UserInfo
userId int = 123
)
destinationList = append(destinationList, UserInfo {
UserId : 23,
})
destinationList = append(destinationList, UserInfo {
UserId : 123,
})
idx := Search(len(destinationList), func(index int) bool {
return destinationList[index].UserId == userId
})
if idx < 0 {
fmt.Println("not found")
} else {
fmt.Println(idx)
}
}
Solution 8:[8]
Another option if your slice is sorted is to use SearchInts(a []int, x int) int which returns the element index if it's found or the index the element should be inserted at in case it is not present.
s := []int{3,2,1}
sort.Ints(s)
fmt.Println(sort.SearchInts(s, 1)) // 0
fmt.Println(sort.SearchInts(s, 4)) // 3
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Hodza |
| Solution 2 | Community |
| Solution 3 | alessandro |
| Solution 4 | 0xInfection |
| Solution 5 | |
| Solution 6 | robothor |
| Solution 7 | omotto |
| Solution 8 | Alan Sereb |
