web-dev-qa-db-de.com

So löschen Sie ein Element aus dem Array in Golang

fmt.Println("Enter position to delete::")
fmt.Scanln(&pos)

new_arr:=make([]int,(len(arr)-1))
k:=0
for i:=0;i<(len(arr)-1);{
  if(i!=pos){
    new_arr[i]=arr[k]
    k++
    i++
  }else{
    k++
  }
}

for i:=0;i<(len(arr)-1);i++{
    fmt.Println(new_arr[i])
}

}

Ich verwende diesen Befehl, um ein Element aus einem Array zu löschen, aber es funktioniert nicht. Bitte schlagen Sie vor.

27
Anchal Sarraf

Bestellung zählt

Wenn Sie Ihr Array geordnet halten möchten, müssen Sie alle Elemente rechts vom Löschindex um eins nach links verschieben. Hoffentlich geht das in Golang einfach:

func remove(slice []int, s int) []int {
    return append(slice[:s], slice[s+1:]...)
}

Dies ist jedoch ineffizient, da am Ende alle Elemente verschoben werden müssen, was teuer ist.

Ordnung ist nicht wichtig

Wenn Sie sich nicht für die Bestellung interessieren, haben Sie die viel schnellere Möglichkeit, das zu löschende Element durch das am Ende des Slice zu löschende Element auszutauschen und dann die ersten n-1-Elemente zurückzugeben:

func remove(s []int, i int) []int {
    s[len(s)-1], s[i] = s[i], s[len(s)-1]
    return s[:len(s)-1]
}

Bei der Reslicing-Methode dauert das Leeren eines Arrays mit 1 000 000 Elementen 224 Sekunden, bei diesem Element sind es nur 0,06 ns. Ich vermute, dass intern nur die Länge des Slice geändert wird, ohne es zu ändern.

Bearbeiten 1

Kurze Notizen basierend auf den Kommentaren (danke!).

Da der Zweck darin besteht, ein Element zu löschen, wird das zweite Element verschwendet, wenn die Reihenfolge keine Rolle spielt.

func remove(s []int, i int) []int {
    s[i] = s[len(s)-1]
    // We do not need to put s[i] at the end, as it will be discarded anyway
    return s[:len(s)-1]
}

Diese Antwort führt auch keinegrenzen-Überprüfung durch. Es erwartet einen gültigen Index als Eingabe. Dies bedeutet, dass negative Werte oder Indizes, die größer oder gleich len (s) sind, zu einer Panik von Go führen. Da Slices und Arrays 0-indiziert sind und das n-te Element eines Arrays entfernt wird, bedeutet dies die Eingabe n-1 . Um das erste Element zu entfernen, rufen Sie remove (s, 0) auf, um das zweite Element zu entfernen, rufen Sie remove (s, 1) usw. auf.

61
T. Claverie

Kleiner Punkt (Code Golf), aber wenn die Reihenfolge keine Rolle spielt, müssen Sie die Werte nicht austauschen. Überschreiben Sie einfach die entfernte Array-Position mit einem Duplikat der letzten Position und geben Sie dann ein abgeschnittenes Array zurück. 

func remove(s []int, i int) []int {
    s[i] = s[len(s)-1]
    return s[:len(s)-1]
}

Gleiches Ergebnis.

19
David

entferne ein Element aus dem Slice:

package main

import (
    "fmt"
)

func RemoveIndex(s []int, index int) []int {
    return append(s[:index], s[index+1:]...)
}

func main() {
    all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    fmt.Println(all) //[0 1 2 3 4 5 6 7 8 9]
    n := RemoveIndex(all, 5)
    fmt.Println(n) //[0 1 2 3 4 6 7 8 9]
}
7
user6169399

Aus dem Buch The Go Programming Language

Um ein Element aus der Mitte eines Slice zu entfernen, wobei die Reihenfolge der verbleibenden Elemente beibehalten wird, verschieben Sie die höher nummerierten Elemente mit copy um eins nach unten, um die Lücke zu füllen:

func remove(slice []int, i int) []int {
  copy(slice[i:], slice[i+1:])
  return slice[:len(slice)-1]
}
5
Oleksandr Mosur

Dies ist etwas seltsam zu sehen, aber die meisten Antworten hier sind gefährlich und beschönigen, was sie tatsächlich tun. Wenn Sie sich die ursprüngliche Frage ansehen, die zum Entfernen eines Elements aus dem Slice gestellt wurde, wird eine Kopie des Slice erstellt und dann gefüllt. Dies stellt sicher, dass Sie keine subtilen Bugs einführen, wenn die Slices durch Ihr Programm geleitet werden.

Hier ist ein Code, der die Antworten der Benutzer in diesem Thread und dem ursprünglichen Beitrag vergleicht. Hier ist ein go playground um mit diesem Code herumzuspielen.

Append-basiertes Entfernen

package main

import (
    "fmt"
)

func RemoveIndex(s []int, index int) []int {
    return append(s[:index], s[index+1:]...)
}

func main() {
    all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
    removeIndex := RemoveIndex(all, 5)

    fmt.Println("all: ", all) //[0 1 2 3 4 6 7 8 9 9]
    fmt.Println("removeIndex: ", removeIndex) //[0 1 2 3 4 6 7 8 9]

    removeIndex[0] = 999
    fmt.Println("all: ", all) //[999 1 2 3 4 6 7 9 9]
    fmt.Println("removeIndex: ", removeIndex) //[999 1 2 3 4 6 7 8 9]
}

Im obigen Beispiel sehen Sie, wie ich ein Slice erstelle und es manuell mit den Nummern 0 bis 9 fülle. Dann entfernen wir den Index 5 von allen und weisen ihn zu, um den Index zu entfernen. Wenn wir jedoch jetzt alle ausdrucken, sehen wir, dass sie ebenfalls geändert wurden. Dies liegt daran, dass Slices Zeiger auf ein zugrunde liegendes Array sind. Durch das Schreiben in removeIndex wird auch all geändert, wobei der Unterschied darin besteht, dass all um ein Element länger ist, das von removeIndex nicht mehr erreichbar ist. Als nächstes ändern wir einen Wert in removeIndex und wir können sehen, dass all ebenfalls geändert wird. Effective go geht darauf näher ein.

Auf das folgende Beispiel werde ich nicht eingehen, aber es macht dasselbe für unsere Zwecke. Und zeigt nur, dass das Kopieren nicht anders ist.

package main

import (
    "fmt"
)

func RemoveCopy(slice []int, i int) []int {
    copy(slice[i:], slice[i+1:])
    return slice[:len(slice)-1]
}

func main() {
    all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
    removeCopy := RemoveCopy(all, 5)

    fmt.Println("all: ", all) //[0 1 2 3 4 6 7 8 9 9]
    fmt.Println("removeCopy: ", removeCopy) //[0 1 2 3 4 6 7 8 9]

    removeCopy[0] = 999
    fmt.Println("all: ", all) //[99 1 2 3 4 6 7 9 9]
    fmt.Println("removeCopy: ", removeCopy) //[999 1 2 3 4 6 7 8 9]
}

Die Fragen ursprüngliche Antwort

Wenn Sie sich die ursprüngliche Frage ansehen, wird das Segment, aus dem ein Element entfernt wird, nicht geändert. Machen Sie die ursprüngliche Antwort in diesem Thread für die meisten Besucher dieser Seite zur bisher besten.

package main

import (
    "fmt"
)

func OriginalRemoveIndex(arr []int, pos int) []int {
    new_arr := make([]int, (len(arr) - 1))
    k := 0
    for i := 0; i < (len(arr) - 1); {
        if i != pos {
            new_arr[i] = arr[k]
            k++
        } else {
            k++
        }
        i++
    }

    return new_arr
}

func main() {
    all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
    originalRemove := OriginalRemoveIndex(all, 5)

    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
    fmt.Println("originalRemove: ", originalRemove) //[0 1 2 3 4 6 7 8 9]

    originalRemove[0] = 999
    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
    fmt.Println("originalRemove: ", originalRemove) //[999 1 2 3 4 6 7 8 9]
}

Wie Sie sehen können, verhält sich diese Ausgabe so, wie es die meisten Menschen erwarten und wahrscheinlich auch wollen. Die Änderung von originalRemove hat keine Änderungen in all zur Folge, und das Entfernen und Zuweisen des Index führt auch nicht zu Änderungen! Fantastisch!

Dieser Code ist allerdings etwas langwierig, daher kann der obige Code in diesen geändert werden.

Eine richtige Antwort

package main

import (
    "fmt"
)

func RemoveIndex(s []int, index int) []int {
    ret := make([]int, 0)
    ret = append(ret, s[:index]...)
    return append(ret, s[index+1:]...)
}

func main() {
    all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
    removeIndex := RemoveIndex(all, 5)

    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
    fmt.Println("removeIndex: ", removeIndex) //[0 1 2 3 4 6 7 8 9]

    removeIndex[0] = 999
    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 9 9]
    fmt.Println("removeIndex: ", removeIndex) //[999 1 2 3 4 6 7 8 9]
}

Fast identisch mit der ursprünglichen Lösung zum Entfernen des Index, jedoch erstellen wir ein neues Slice, an das wir es anhängen, bevor wir zurückkehren.

2
mschuett

Sie müssen nicht jedes einzelne Element überprüfen, es sei denn, Sie kümmern sich um den Inhalt und können Slice-Anhänge verwenden. Versuch es

pos := 0
arr := []int{1, 2, 3, 4, 5, 6, 7, 9}
fmt.Println("input your position")
fmt.Scanln(&pos)
/* you need to check if negative input as well */
if (pos < len(arr)){
    arr = append(arr[:pos], arr[pos+1:]...)
} else {
    fmt.Println("position invalid")
}
0
GoGo