如何在切片中找到元素的位置?

huangapple go评论85阅读模式
英文:

How to find out element position in slice?

问题

如何确定切片中存在的元素的位置?

我需要类似以下的代码:

type intSlice []int

func (slice intSlice) pos(value int) int {
    for p, v := range slice {
        if (v == value) {
            return p
        }
    }
    return -1
}
英文:

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
}

答案1

得分: 81

抱歉,没有通用的库函数可以做到这一点。Go语言没有一种直接的方法来编写一个可以操作任何切片的函数。

您的函数是有效的,尽管如果您使用range来编写它会更好一些。

如果您碰巧有一个字节切片,可以使用bytes.IndexByte函数。

英文:

Sorry, there's no generic library function to do this. Go doesn't have a straight forward way of writing a function that can operate on any slice.

Your function works, although it would be a little better if you wrote it using range.

If you happen to have a byte slice, there is bytes.IndexByte.

答案2

得分: 71

你可以按照Go语言的惯用方式创建通用函数:

func SliceIndex(limit int, predicate func(i int) bool) int {
    for i := 0; i < limit; i++ {
        if predicate(i) {
            return i
        }
    }
    return -1
}

使用方法:

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" }))
英文:

You can create generic function in idiomatic go way:

func SliceIndex(limit int, predicate func(i int) bool) int {
    for i := 0; i &lt; limit; i++ {
        if predicate(i) {
            return i
        }
    }
    return -1
}

And usage:

xs := []int{2, 4, 6, 8}
ys := []string{&quot;C&quot;, &quot;B&quot;, &quot;K&quot;, &quot;A&quot;}
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] == &quot;Z&quot; }),
    SliceIndex(len(ys), func(i int) bool { return ys[i] == &quot;A&quot; }))

答案3

得分: 28

你可以编写一个函数;

func indexOf(element string, data []string) (int) {
   for k, v := range data {
       if element == v {
           return k
       }
   }
   return -1	//未找到。
}

这个函数会返回字符/字符串的索引,如果匹配到了元素。如果未找到,则返回-1。

英文:

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.

答案4

得分: 8

没有这方面的库函数。你必须自己编写代码。

英文:

There is no library function for that. You have to code by your own.

答案5

得分: 8

Go在1.18版本中支持泛型,这使得你可以创建一个像下面这样的函数:

func IndexOf[T comparable](collection []T, el T) int {
	for i, x := range collection {
		if x == el {
			return i
		}
	}
	return -1
}

如果你想在你的集合上调用IndexOf,你可以选择使用评论中@mh-cbon的技术。

英文:

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.

答案6

得分: 6

自Go 1.18起,您还可以使用来自https://pkg.go.dev/golang.org/x/exp/slices的实验性通用切片包,如下所示:

package main

import "golang.org/x/exp/slices"

func main() {
    s := []int{1,2,3,4,5}
    wanted := 3
    idx := slices.Index(s, wanted)
    fmt.Printf("要查找的元素 %v 的索引是 %v", wanted, idx)
}

如果切片中不存在wanted,它将返回-1。在playground上进行测试。

这是我首选的方法,因为它有可能成为标准库的一部分。

英文:

Since Go 1.18 you can also use the experimental generic slices package from https://pkg.go.dev/golang.org/x/exp/slices like this:

package main

import &quot;golang.org/x/exp/slices&quot;

func main() {
    s := []int{1,2,3,4,5}
    wanted := 3
    idx := slices.Index(s, wanted)
    fmt.Printf(&quot;the index of %v is %v&quot;, wanted, idx)
}

It will return -1, if wanted is not in the slice. Test it at the playground.

This is my preferred way, since this might become part of the standard library someday.

答案7

得分: 5

你可以只迭代切片并检查元素是否与你选择的元素匹配。

英文:

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
}

答案8

得分: 1

另一种选择是使用sort包对切片进行排序,然后搜索你要查找的内容:

package main

import (
	&quot;sort&quot;
	&quot;log&quot;
	)

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(&quot;Sorted: &quot;, a)
    	log.Println(&quot;Found at index &quot;, pos)
}

打印结果为:

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

这适用于基本类型,如果你需要处理其他类型的切片,你可以实现排序接口。参见http://golang.org/pkg/sort

具体取决于你要做什么。

英文:

Another option is to sort the slice using the sort package, then search for the thing you are looking for:

package main

import (
	&quot;sort&quot;
	&quot;log&quot;
	)

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(&quot;Sorted: &quot;, a)
    	log.Println(&quot;Found at index &quot;, 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.

答案9

得分: 0

我几个月前遇到了同样的问题,我用两种方法解决了:

第一种方法:

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
}

使用示例:

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)	
	}
}

第二种方法,计算成本较低:

func Search(length int, f func(index int) bool) int {
	for index := 0; index < length; index++ {
		if f(index) {
			return index
		}
	}
	return -1
}

使用示例:

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)	
	}
}
英文:

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 &lt; 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 &lt; 0 {
		fmt.Println(&quot;not found&quot;)
	} else {
		fmt.Println(idx)	
	}
}

Second method with less computational cost:

func Search(length int, f func(index int) bool) int {
	for index := 0; index &lt; 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 &lt; 0 {
		fmt.Println(&quot;not found&quot;)
	} else {
		fmt.Println(idx)	
	}
}

答案10

得分: 0

如果你的切片是排序的,另一个选项是使用SearchInts(a []int, x int) int函数,它会返回元素的索引(如果找到)或者元素应该插入的索引(如果不存在)。

s := []int{3,2,1}
sort.Ints(s)
fmt.Println(sort.SearchInts(s, 1)) // 0
fmt.Println(sort.SearchInts(s, 4)) // 3

https://play.golang.org/p/OZhX_ymXstF

英文:

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

https://play.golang.org/p/OZhX_ymXstF

答案11

得分: 0

在Go 1.21及更高版本中使用slices.Index

haystack := []string{"foo", "bar", "quux"}
fmt.Println(slices.Index(haystack, "bar")) // 输出 1
fmt.Println(slices.Index(haystack, "rsc")) // 输出 -1
英文:

Use slices.Index in Go 1.21 and later.

haystack := []string{&quot;foo&quot;, &quot;bar&quot;, &quot;quux&quot;}
fmt.Println(slices.Index(haystack, &quot;bar&quot;)) // prints 1
fmt.Println(slices.Index(haystack, &quot;rsc&quot;)) // prints -1

huangapple
  • 本文由 发表于 2011年11月29日 15:57:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/8307478.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定