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


108

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

我需要以下内容:

type intSlice []int

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

2
那么,有什么问题呢?代码不起作用吗?
newacct 2011年

8
我在问为什么程序员要自己编写这样的通用功能?我的意思是,如果我想要另一个用于浮点值的函数,我将被迫复制/粘贴此函数。这对我来说很奇怪。但是Krzysztof Kowalczyk已经回答了,这是因为golang没有泛型。
OCyril 2011年

您的切片排序了吗?
2015年

Answers:


70

抱歉,没有通用库函数可以执行此操作。Go并没有直接的方法来编写可以在任何片段上运行的函数。

您的函数可以运行,尽管如果使用编写它会更好一些range

如果碰巧有一个字节片,则为bytes.IndexByte


3
我同意埃文。补充说明:返回-1表示“未找到”(例如bytes.IndexByte)的int更为惯用
Krzysztof Kowalczyk

2
谢谢。但是我有点不知所措:)我多次听到使用golang的人说,它设计得很好,可以提高程序员的工作效率。go程序看起来和python一样好:)那么,为什么没有一种通用的方法来完成这种通用任务呢?我的意思是,如果您想检查容器中是否有元素,可以if element in collection: do_something()
OCyril

10
技术上的答案是:因为Go没有泛型。如果可以的话(也许将来会出现),您可能已经编写了一个通用的IndexInSlice,它可以在实现==的任何类型上使用。戴上我的Go倡导者帽子:这是一次普通的体验。您不能期望一种语言在各个方面都能胜过其他所有语言。围棋比C,C ++,甚至Java或C#,靠近蟒蛇更富有成效。正是程序员效率与本机代码生成(即速度)的结合才使其具有吸引力。
Krzysztof Kowalczyk

1
另一种选择是使用高阶函数和闭包来创建泛型函数。我用示例添加了答案。
Hodza

1
@OCyril您必须编写自己的泛型并建立自己的库或进行研究,找到适合您需求的东西。在最低级别上,“在数组中查找值= x”功能(PHP,Python或其他)在某种程度上看起来类似于OP问题中给出的版本-在较低级别上。循环对于这种编程至关重要,即使它们是隐藏的。Go不会隐藏这些东西。
伊恩·刘易斯

54

您可以按惯用的方式创建通用函数:

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

1
喜欢这个,但我确实很难以这种方式想到它
Decebal 2015年

1
我认为-1错误返回不是惯用的,它应该使用多次返回。(我是Golang的新手,但我已经读过这本书)
Tim Abell

7
go中的Buildtin索引函数始终返回-1。这是预期的惯用行为。缺少元素不是错误。
Hodza

这是太棒了!非常有用:)谢谢!
Gaurav Ojha

12

您可以编写一个函数;

func indexOf(element string, data []string) (int) {
   for k, v := range data {
       if element == v {
           return k
       }
   }
   return -1    //not found.
}

如果与元素匹配,则返回字符/字符串的索引。如果找不到,则返回-1。



2
func index(slice []string, item string) int {
    for i, _ := range slice {
        if slice[i] == item {
            return i
        }
    }
    return -1
}

1

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

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

版画

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

这适用于基本类型,如果需要处理其他事情,则始终可以为自己的类型实现sort接口。参见http://golang.org/pkg/sort

取决于您在做什么。


好,谢谢。但是我想如果我只想检查slice是否包含给定的元素,使用它似乎很奇怪:)
OCyril

3
这找不到原始索引;而是通过重新排序来丢失所有索引
newacct

当然,这就是它取决于用法的原因。如果只是检查,请确保使用for p, v := range ...if。只是想指出选项。
robothor
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.