Подтвердить что ты не робот

Как изменить массив в Go?

http://play.golang.org/p/W70J4GU7nA

  s := []int{5, 2, 6, 3, 1, 4}
  sort.Reverse(sort.IntSlice(s))
  fmt.Println(s)
  // 5, 2, 6, 3, 1, 4

Трудно понять, что это означает в интерфейсе func Reverse (интерфейс данных).

Как мне изменить массив? Мне не нужно сортировать.

4b9b3361

Ответ 1

Обычно для сортировки массива целых чисел вы переносите их в IntSlice, который определяет методы Len, Less и Swap. Эти методы, в свою очередь, используются sort.Sort. Что делает sort.Reverse, так это то, что он принимает существующий тип, который определяет Len, Less и Swap, но заменяет метод Less на новый, который всегда является обратным базовому Less

type reverse struct {
    // This embedded Interface permits Reverse to use the methods of
    // another Interface implementation.
    Interface
}

// Less returns the opposite of the embedded implementation Less method.
func (r reverse) Less(i, j int) bool {
    return r.Interface.Less(j, i)
}

// Reverse returns the reverse order for data.
func Reverse(data Interface) Interface {
    return &reverse{data}
}

Итак, когда вы пишете sort.Reverse(sort.IntSlice(s)), происходит то, что вы получаете этот новый, "измененный" IntSlice, который заменил метод Less. Поэтому, если вы назовете sort.Sort на нем, который вызывает Less, он будет отсортирован в порядке убывания.

Ответ 2

Честно говоря, это достаточно просто, так что я бы просто написал это так:

package main

import "fmt"

func main() {

    s := []int{5, 2, 6, 3, 1, 4}

    for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
        s[i], s[j] = s[j], s[i]
    }

    fmt.Println(s)
}

http://play.golang.org/p/vkJg_D1yUb

(Другие ответы хорошо объясняют sort.Interface и как его использовать; поэтому я не буду повторять это.)

Ответ 3

Я опаздываю на 2 года, но просто для удовольствия и интереса хочу внести свой вклад в решение "странного".

Предполагая, что задача состоит в том, чтобы обратить вспять список, то для необработанной производительности bgp решение, вероятно, непревзойденно. Это упрощает и упрощает работу, сводя элементы массива вперед-назад, операцию, эффективную в структуре произвольного доступа массивов и фрагментов.

В языках функционального программирования идиоматический подход часто предполагает рекурсию. Это выглядит немного странно в Go и будет иметь ужасную производительность. При этом здесь рекурсивная функция разворота массива (в небольшой тестовой программе):

package main

import (
    "fmt"
)

func main() {
    myInts := []int{ 8, 6, 7, 5, 3, 0, 9 }
    fmt.Printf("Ints %v reversed: %v\n", myInts, reverseInts(myInts))
}

func reverseInts(input []int) []int {
    if len(input) == 0 {
        return input
    }
    return append(reverseInts(input[1:]), input[0]) 
}

Вывод:

Ints [8 6 7 5 3 0 9] reversed: [9 0 3 5 7 6 8]

Опять же, это для удовольствия, а не для производства. Он не только медленный, но и переполняет стек, если список слишком велик. Я только что протестировал, и он изменит список из 1 миллиона int, но сработает на 10 миллионов.

Ответ 4

Прежде всего, если вы хотите изменить массив, сделайте это,

for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
    a[i], a[j] = a[j], a[i]
}

Затем посмотрите на использование Reverse в golang.org

package main

import (
    "fmt"
    "sort"
)

func main() {
    s := []int{5, 2, 6, 3, 1, 4} // unsorted
    sort.Sort(sort.Reverse(sort.IntSlice(s)))
    fmt.Println(s)
}

// output
// [6 5 4 3 2 1]

И посмотрите описание Reverse and Sort

func Reverse(data Interface) Interface
func Sort(data Interface)

Сортировка сортирует данные. Он делает один вызов данных. Можно определить n и O (n * log (n)) вызывает данные. Less и data.Swap. Сорт не гарантированно стабилен.

Итак, как вы знаете, Sort - это не просто алгоритм сортировки, вы можете просмотреть его как factory, когда вы используете Reverse, он просто возвращает обратный алгоритм сортировки, Сортировка просто выполняет сортировку.

Ответ 5

Это более общая функция резания среза. Он будет паниковать, если вход не является срезом.

//panic if s is not a slice
func ReverseSlice(s interface{}) {
    size := reflect.ValueOf(s).Len()
    swap := reflect.Swapper(s)
    for i, j := 0, size-1; i < j; i, j = i+1, j-1 {
        swap(i, j)
    }
}

Ответ 6

Если вы хотите перевернуть массив, вы можете просто пройти через него в обратном порядке. Поскольку в языке нет примитива "обратный диапазон" (по крайней мере, пока), вы должны сделать что-то вроде этого (http://play.golang.org/p/AhvAfMjs_7):

s := []int{5, 2, 6, 3, 1, 4}
for i := len(s) - 1; i >= 0; i-- {
    fmt.Print(s[i])
    if i > 0 {
        fmt.Print(", ")
    }
}
fmt.Println()

Относительно того, трудно ли понять, что делает sort.Reverse(data Interface) Interface, я думал так же, пока не увидел исходный код изhttp://golang.org/src/pkg/sort/sort.go.

Это просто делает сравнения, необходимые для сортировки, чтобы быть "наоборот".

Ответ 7

func Reverse(data Interface) Interface

Это означает, что он принимает sort.Interface и возвращает другой sort.Interface - он фактически не выполняет никакой сортировки. Например, если вы перейдете в sort.IntSlice (который по существу является []int, который может быть передан в sort.Sort для сортировки в порядке возрастания), вы получите новый sort.Interface, который сортирует ints в порядке убывания вместо.

Кстати, если вы нажмете на имя функции в документацию, она напрямую свяжется с источник для Reverse. Как вы можете видеть, он просто переносит sort.Interface, который вы передаете, поэтому значение, возвращаемое из Reverse, получает все методы исходного sort.Interface. Единственный метод, отличный от метода Less, который возвращает противоположность метода Less во встроенном sort.Interface. Подробнее о встроенных полях см. эту часть спецификации языка.

Ответ 8

Вот еще один способ сделать это

func main() {
    example := []int{1, 25, 3, 5, 4}
    sort.SliceStable(example, func(i, j int) bool {
        return true
    })
    fmt.Println(example)
}

https://play.golang.org/p / -tIzPX2Ds9z

Ответ 9

Вот простое решение Go, которое использует эффективный (без дополнительной памяти) подход для обращения массива:

i := 0
j := len(nums) - 1
for i < j {
    nums[i], nums[j] = nums[j], nums[i]
    i++
    j--
}

Идея состоит в том, что обращение массива эквивалентно замене каждого элемента его зеркальным отображением по центру.

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

Ответ 10

Чтобы отменить массив на месте, перейдите в его среднюю точку и замените каждый элемент его "зеркальным элементом":

func main() {
    xs := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
    itemCount := len(xs)
    for i := 0; i < itemCount/2; i++ {
        mirrorIdx := itemCount - i -1
        xs[i], xs[mirrorIdx] = xs[mirrorIdx], xs[i]
    }
    fmt.Printf("xs: %v\n", xs)
}

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

Ответ 11

Из Вики-сайта Golang SliceTricks:

Заменить содержимое среза теми же элементами, но в обратный порядок:

for i := len(a)/2-1; i >= 0; i-- {
  opp := len(a)-1-i
  a[i], a[opp] = a[opp], a[i]
}

То же самое, за исключением двух индексов:

for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 {
  a[left], a[right] = a[right], a[left]
}

Ответ 12

Вот мое решение для обращения массива:

func reverse_array(array []string) []string {
    lenx := len(array) // lenx holds the original array length
    reversed_array := make([]string, lenx) // creates a slice that refer to a new array of length lenx

    for i := 0; i < lenx; i++ {
        j := lenx - (i + 1) // j initially holds (lenx - 1) and decreases to 0 while i initially holds 0 and increase to (lenx - 1)
        reversed_array[i] = array[j]
    }

    return reversed_array
}

Вы можете попробовать это решение на игровой площадке Го игровая площадка

package main

import "fmt"

func main() {
    array := []string{"a", "b", "c", "d"}

    fmt.Println(reverse_array(array)) // prints [d c b a]
}

Ответ 13

Не переверните его, оставьте его как сейчас, а затем просто переместите его назад.