Как изменить массив в 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 (интерфейс данных).
Как мне изменить массив? Мне не нужно сортировать.
Ответы
Ответ 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
Не переверните его, оставьте его как сейчас, а затем просто переместите его назад.