Як дізнатися положення елемента в зрізі?


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

8
Я запитував, чому мусять кодери самі писати такі загальні функції? Я маю на увазі, якщо я хочу іншу функцію для плаваючих значень, я змушений буде скопіювати / вставити цю функцію. Це виглядало для мене дивно. Але Кшиштоф Ковальчик вже відповів, що це тому, що голанг не має дженериків.
квітня

Чи сортований ваш шматочок?
долмен

2
Спробуйте це джерело: gobyexample.com/collection-functions
Віктор

Відповіді:


70

Вибачте, для цього немає загальної бібліотечної функції. Go не має прямого способу написання функції, яка може працювати на будь-якому фрагменті.

Ваша функція працює, хоча було б трохи краще, якби ви написали її за допомогою range.

Якщо у вас трапляється фрагмент байта, є байт.IndexByte .


3
Я згоден з Еваном. Додатковий коментар: ідіоматичніше повернути лише int, де -1 вказує "не знайдено" (наприклад, bytes.IndexByte)
Кшиштоф Ковальчик

2
Дякую. Але я трохи переповнений :) Я багато разів чув від людей, які використовують голанг, що він дуже добре розроблений для підвищення продуктивності програміста. І go go програми виглядають так само приємно, як і python :) Так чому ж немає спільного способу зробити таке спільне завдання? Я маю на увазі, якщо ви хочете перевірити, чи є у контейнера елемент, ви можете простоif element in collection: do_something()
жовтня 11

10
Технічна відповідь: тому що Go не має дженериків. Якби це було (і, можливо, в якийсь момент у майбутньому він буде мати їх), ви могли б написати загальний IndexInSlice, який працює на будь-якому типі, що реалізує ==. Одягаючи мою шапку Go advocate: йдеться про середній досвід. Ви не можете очікувати, що одна мова переможе будь-яку іншу мову в кожному аспекті. Go є набагато більш продуктивним , ніж C, C ++, може бути , навіть Java або C # і близько до пітонові. Це поєднання продуктивності програміста та генерації коду (тобто швидкості) робить його привабливим.
Кшиштоф Ковальчик

1
Інший варіант - використовувати функції вищого порядку та закриття для створення загальних функцій. Я додав відповідь прикладом.
Ходжа

1
@OCyril Ви повинні написати власні дженерики та створити власну бібліотеку або зробити дослідження та знайти щось, що відповідає вашим потребам. На найнижчому рівні функція 'find value = x in array' (PHP, Python або інше) буде дещо схожа на версію, задану у запитанні ОП - на низькому рівні. Петлі є центральними для цього виду програмування, навіть якщо вони приховані. 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
Люблю це, але мені важко придумати це так
грудень

1
Я не думаю, що повернення -1для помилки є ідіоматичним, замість цього слід використовувати кілька повернень. (Я новачок у golang, але це те, що я прочитав)
Тім Абелл

7
Індекс indeks Buildtin функціонує завжди повертається -1. Очікується ідіоматична поведінка. Відсутній елемент не є помилкою.
Ходжа

Це фантастично! Дуже корисно :) Дякую!
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

Іншим варіантом є сортування фрагмента за допомогою пакету сортування, а потім пошук потрібної речі:

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

Це працює для основних типів, і ви завжди можете реалізувати інтерфейс сортування для власного типу, якщо вам потрібно працювати над фрагментом інших речей. Див. Http://golang.org/pkg/sort

Залежить від того, чим ти займаєшся.


Добре, дякую. Але я думаю, що дивно використовувати це, якщо я хочу лише перевірити, чи містить фрагмент заданий елемент :)
квітня

3
це не знаходить початкового індексу; скоріше він втрачає всі індекси, повторно замовляючи їх
newacct

Звичайно, саме тому це залежить від використання. Якщо це просто перевірка, то впевнено, просто використовуйте for p, v := range ...і if. Просто хотілося вказати на варіант.
роботор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.