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

我正在使用这个命令从切片中删除一个元素,但它不起作用,请建议。


当前回答

次要点(代码高尔夫),但在顺序不重要的情况下,你不需要交换值。只需用上一个位置的副本覆盖被删除的数组位置,然后返回一个截断的数组。

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

相同的结果。

其他回答

没有必要检查每一个元素,除非你关心的内容,你可以利用切片追加。试试吧

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

也许你可以试试这个方法:

// DelEleInSlice delete an element from slice by index
//  - arr: the reference of slice
//  - index: the index of element will be deleted
func DelEleInSlice(arr interface{}, index int) {
    vField := reflect.ValueOf(arr)
    value := vField.Elem()
    if value.Kind() == reflect.Slice || value.Kind() == reflect.Array {
        result := reflect.AppendSlice(value.Slice(0, index), value.Slice(index+1, value.Len()))
        value.Set(result)
    }
}

用法:

arrInt := []int{0, 1, 2, 3, 4, 5}
arrStr := []string{"0", "1", "2", "3", "4", "5"}
DelEleInSlice(&arrInt, 3)
DelEleInSlice(&arrStr, 4)
fmt.Println(arrInt)
fmt.Println(arrStr)

结果:

0, 1, 2, 4, 5
"0", "1", "2", "3", "5"

顺序很重要

如果你想要保持数组的有序,你必须将删除索引右边的所有元素向左移动一个单位。希望在Golang中可以轻松做到这一点:

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

然而,这是低效的,因为您可能最终要移动所有的元素,这是昂贵的。

顺序并不重要

如果你不关心顺序,你可以更快地将要删除的元素替换为片末尾的元素,然后返回第n-1个元素:

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

使用reslicing方法,清空一个包含100万个元素的数组需要224秒,而这个方法只需要0.06ns。

这个答案不执行边界检查。它需要一个有效的索引作为输入。这意味着大于或等于初始len(s)的负值或下标将导致Go panic。

切片和数组是0索引,删除数组的第n个元素意味着提供输入n-1。要删除第一个元素,调用remove(s, 0),要删除第二个元素,调用remove(s, 1),依此类推。

T. Claverie目前投票最多的答案是正确的,但我发现如果只在需要时执行交换,即对片的最后一个元素以外的所有元素执行交换,算法会更清晰。这可以通过一个简单的if守卫来实现。

秩序不重要/没有进行边界检查

func remove(s []int, i int) []int {
    // bring element to remove at the end if its not there yet
    if i != len(s)-1 {
        s[i] = s[len(s)-1]
    }
 
    // drop the last element
    return s[:len(s)-1]
}

找到一条不需要搬迁的路。

更改订单

a := []string{"A", "B", "C", "D", "E"}
i := 2

// Remove the element at index i from a.
a[i] = a[len(a)-1] // Copy last element to index i.
a[len(a)-1] = ""   // Erase last element (write zero value).
a = a[:len(a)-1]   // Truncate slice.

fmt.Println(a) // [A B E D]

维持秩序

a := []string{"A", "B", "C", "D", "E"}
i := 2

// Remove the element at index i from a.
copy(a[i:], a[i+1:]) // Shift a[i+1:] left one index.
a[len(a)-1] = ""     // Erase last element (write zero value).
a = a[:len(a)-1]     // Truncate slice.

fmt.Println(a) // [A B D E]