2013-10-08 7 views
28

http://play.golang.org/p/W70J4GU7nAWie reverse ich ein Array in Go?

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

Es ist schwer zu verstehen, was in func Rückwärts (Data Interface) Schnittstelle bedeutet.

Wie kann ich ein Array umkehren? Ich muss nicht sortieren.

+0

Siehe http://stackoverflow.com/questions/18343208/how-to-reverse-sort-a-slice-of-integer-golang. Ich denke, du musst "Sortieren" verwenden, um es einfach zu machen. – Intermernet

Antwort

16

Um ein Array von ganzen Zahlen zu sortieren, wickeln Sie sie normalerweise in IntSlice ein, das die Methoden Len, Less und Swap definiert. Diese Methoden werden wiederum von sort.Sort verwendet. Was sort.Reverse tut, ist, dass es eine bestehende Art nimmt die Len definiert, Less und Swap, aber es ersetzt die Less Methode durch eine neue, die immer die Umkehrung des zugrunde liegenden Less ist:

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

Also, wenn Sie schreiben sort.Reverse(sort.IntSlice(s)), was passiert ist, dass Sie bekommen diese neue, 'modifizierte' IntSlice, die es Less Methode ersetzt hat. Also, wenn Sie sort.Sort darauf anrufen, die Less ruft, wird es in absteigender Reihenfolge sortiert.

3
func Reverse(data Interface) Interface 

Das bedeutet, dass es eine sort.Interface und gibt eine andere sort.Interface nimmt - es jeder Sortier- selbst eigentlich nicht tun. Wenn Sie beispielsweise sort.IntSlice übergeben (was im Wesentlichen eine []int ist, die an sort.Sort übergeben werden kann, um sie in aufsteigender Reihenfolge zu sortieren), erhalten Sie eine neue sort.Interface, die die Ints in absteigender Reihenfolge sortiert.

Übrigens, wenn Sie auf den Funktionsnamen in the documentation klicken, verbindet es sich direkt mit the source für Reverse. Wie Sie sehen können, wird nur die sort.Interface übergeben, die Sie übergeben, so dass der von Reverse zurückgegebene Wert alle Methoden des ursprünglichen sort.Interface erhält. Die einzige Methode, die anders ist, ist die Less Methode, die das Gegenteil der Less Methode auf dem eingebetteten sort.Interface zurückgibt. Details zu eingebetteten Feldern finden Sie unter this part of the language spec.

64

Ehrlich dies ist einfach genug, dass ich es einfach so aus schreiben würde:

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

(Die anderen Antworten machen einen guten Job es zu erklären, Interface und wie zu verwenden; also werde ich das nicht wiederholen.)

4

Wenn Sie das Array umkehren möchten, können Sie es in umgekehrter Reihenfolge durchlaufen. Da es keine „Rückwärtsbereich“ primitive in der Sprache (zumindest noch nicht) ist, müssen Sie etwas tun (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() 

darüber, ob es schwer zu verstehen ist, was sort.Reverse(data Interface) Interface tut, dachte ich, die bis ich den Quellcode von "http://golang.org/src/pkg/sort/sort.go" sah.

Es macht nur die Vergleiche erforderlich für die Sortierung "andersherum" gemacht werden.

7

Ich bin 2 Jahre zu spät, aber nur aus Spaß und Interesse möchte ich eine "Oddball" -Lösung beitragen.

Angenommen, die Aufgabe ist wirklich, eine Liste umzukehren, dann ist die Lösung für die rohe Leistung bgp wahrscheinlich unschlagbar. Die Aufgabe wird einfach und effektiv erledigt, indem Array-Elemente von vorne nach hinten getauscht werden, eine Operation, die effizient in der Random-Access-Struktur von Arrays und Slices ist.

In funktionalen Programmiersprachen würde der idiomatische Ansatz oft Rekursion beinhalten. Das sieht in Go ein bisschen komisch aus und wird eine schreckliche Leistung haben. Das heißt, hier ist eine rekursive Array-Umkehrfunktion (in einem kleinen Testprogramm):

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

Ausgang:

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

Auch dies ist für Spaß und nicht die Produktion. Es ist nicht nur langsam, aber es wird den Stapel überlaufen, wenn die Liste zu groß ist. Ich habe gerade getestet, und es wird eine Liste von 1 Million int s umkehren, aber stürzt auf 10 Millionen ab.

+1

Für die Neugierigen gibt es nur begrenzte TCO in Go: http://stackoverflow.com/questions/12102675/tail-call-optimization-in-go – Lloeki

3

Zunächst einmal, wenn Sie das Array umkehren wollen, wie dies zu tun,

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

Dann sehen Sie die Verwendung von Reverse in 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] 

Und bei der Suche Beschreibung von Reverse und Sortieren

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

sortieren sortiert Daten. Es macht einen Aufruf an data.Len, um n und O (n * log (n)) Aufrufe an data.Less und data.Swap zu bestimmen. Die Art ist nicht garantiert stabil zu sein.

So, wie Sie wissen, ist Sortieren nicht nur ein Sortieralgorithmus, können Sie es als eine Fabrik sehen können, wenn Sie umkehren verwenden es nur eine umgekehrte Sortieralgorithmus zurückkehren, Sort ist nur die Sortierung zu tun.

+0

Sie sollten wahrscheinlich nur bis zum Mittelpunkt des Arrays durchlaufen: https://play.golang.org/p/JeSApt80_k –

0

ein Array anstelle umzukehren, um seinen mittleren Punkt iterieren, und jedes Element mit seinem "Spiegelelement" SWAP:

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

Dies ist eine allgemeinerer slice Umkehrfunktion . Es wird in Panik geraten, wenn die Eingabe keine Scheibe ist.

//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

Nicht umkehren, lassen Sie es wie jetzt und dann wiederholen Sie es einfach rückwärts.

+0

lol was? Kein Rückwärtsfahren erlaubt? – Zachscs