2013-10-08 16 views
28

http://play.golang.org/p/W70J4GU7nAJak odwrócić tablicę w Go?

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

Trudno jest zrozumieć, co to znaczy w func odwróconych (Data Interface) interfejs.

Jak odwrócić tablicę? Nie muszę sortować.

+0

Zobacz http://stackoverflow.com/questions/18343208/how-to-reverse-sort-a-slice-of-integer-golang. Myślę, że musisz użyć 'Sortuj', aby zrobić to łatwo. – Intermernet

Odpowiedz

16

Normalnie, aby posortować tablicę liczb całkowitych, zawinąć je w IntSlice, który definiuje metody Len, Less i Swap. Te metody są z kolei używane przez sort.Sort. Co sort.Reverse robi to, że zajmuje istniejącego typu definiujący Len, Less i Swap, ale zastępuje metodę Less na nową, która jest zawsze odwrotnością leżącej 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's 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} 
} 

Więc kiedy piszesz sort.Reverse(sort.IntSlice(s)), dzieje się tak, że otrzymujesz ten nowy, "zmodyfikowany" IntSlice, który zastąpił metodę Less. Więc jeśli zadzwonisz na numer sort.Sort, który wywoła Less, zostanie posortowany w kolejności malejącej.

3
func Reverse(data Interface) Interface 

Oznacza to, że zajmuje sort.Interface i zwraca inny sort.Interface - faktycznie nie robi każdy sortowania się. Na przykład, jeśli przekażemy sort.IntSlice (który jest w zasadzie []int, który można przekazać do sort.Sort, aby posortować go w porządku rosnącym), otrzymasz nowy sort.Interface, który sortuje ints w kolejności malejącej.

Nawiasem mówiąc, jeśli klikniesz nazwę funkcji w the documentation, zostanie ona bezpośrednio połączona z the source dla Reverse. Jak widać, po prostu owija sort.Interface, który przekazujesz, więc wartość zwrócona z Reverse uzyskuje wszystkie metody oryginalnego sort.Interface. Jedyna metoda, która jest inna, to metoda Less, która zwraca przeciwieństwo metody Less na osadzonym sort.Interface. Zobacz this part of the language spec, aby uzyskać szczegółowe informacje na temat pól osadzonych.

64

Szczerze ten jest na tyle prosta, że ​​ja po prostu napisać go tak:

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

(innych odpowiedzi zrobić dobrą robotę wyjaśniając Interface i jak go używać; więc nie powtórzę tego.)

4

Jeśli chcesz odwrócić tablicę, możesz po prostu przejść przez nią w odwrotnej kolejności. Ponieważ nie ma „reverse zakres” prymitywne w języku (przynajmniej jeszcze nie), musisz zrobić coś takiego (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() 

chodzi czy trudno jest zrozumieć, co sort.Reverse(data Interface) Interface robi, myślałem, że tak samo, dopóki nie zobaczyłem kodu źródłowego z "http://golang.org/src/pkg/sort/sort.go".

Po prostu dokonuje porównań wymaganych do wykonania sortowania "na odwrót".

7

Spóźniam się dwa lata, ale dla zabawy i zainteresowania chciałbym wnieść wkład w "dziwne" rozwiązanie.

Zakładając, że zadaniem jest na pewno odwrócenie listy, to dla nieprzetworzonego rozwiązania bgp jest prawdopodobnie nie do pokonania. Robi to zadanie w prosty i skuteczny sposób, zamieniając elementy tablicy na przednie i tylne, operację, która jest wydajna w strukturze dostępu losowego macierzy i wycinków.

W językach programowania funkcjonalnego podejście idiomatyczne często wymagałoby rekurencji. To wygląda trochę dziwnie w Go i będzie miało okropną wydajność. Powiedział, że tu jest rekurencyjna funkcja odwrócenia array (w małym programem testowym):

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

wyjściowa:

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

Ponownie, jest to dla zabawy, a nie produkcji. Nie tylko jest powolny, ale spowoduje przepełnienie stosu, jeśli lista jest zbyt duża. Właśnie przetestowałem i odwróci listę 1 miliona int s, ale zawiesza się na 10 milionach.

+1

Dla ciekawych, jest tylko ograniczony TCO w Go: http://stackoverflow.com/questions/12102675/tail-call-optimization-in-go – Lloeki

3

Przede wszystkim, jeśli chcesz odwrócić tablicę, jak to zrobić,

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

Następnie spojrzeć na korzystanie z odwróceniu 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] 

i spojrzeć na dane i opis odwrotnej Sortuj

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

sort sortuje. Wykonuje jedno połączenie z danymi. Aby ustalić połączenia n i O (n * log (n)) do danych. Bez danych i danych. Zamiana. Sortowanie nie gwarantuje stabilności.

Tak, jak pan wie, Sort nie tylko algorytm sortowania, można go zobaczyć w fabryce, podczas korzystania z tyłu po prostu wrócić algorytm sortowania odwrócone, sortowania jest po prostu robi sortowania.

+0

Prawdopodobnie powinieneś tylko iterować do środkowego punktu tablicy: https://play.golang.org/p/JeSApt80_k –

0

celu odwrócenia tablicy w miejscu iterację na jego punktu środkowego i wymiany poszczególnych elementów z „element lustrzanym”:

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

1

To jest bardziej ogólnych funkcji plaster odwrotnej . Będzie panikował, jeśli wejście nie jest plastrem.

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

Nie zamieniaj go, pozostaw tak jak teraz, a następnie po prostu wykonaj iterację wstecz.

+0

lol co? Nie zezwala się na cofanie? – Zachscs

Powiązane problemy