[go] 슬라이스에서 요소 삭제

func main() {
    a := []string{"Hello1", "Hello2", "Hello3"}
    fmt.Println(a)
    // [Hello1 Hello2 Hello3]
    a = append(a[:0], a[1:]...)
    fmt.Println(a)
    // [Hello2 Hello3]
}

추가 기능을 사용하면 삭제 트릭이 어떻게 작동합니까?

첫 번째 요소 (빈 배열) 전에 모든 것을 잡는 것처럼 보입니다.

그런 다음 첫 번째 요소 뒤에 모든 것을 추가하십시오 (위치 0)

… (도트 도트 도트)의 기능은 무엇입니까?



답변

a슬라이스는 어디에 있고 i삭제할 요소의 인덱스는 다음 과 같습니다.

a = append(a[:i], a[i+1:]...)

... Go의 variadic 인수에 대한 구문입니다.

기본적으로 함수를 정의 할 때 전달 하는 모든 인수를 해당 유형의 한 조각에 넣습니다. 그렇게하면 원하는만큼 많은 인수를 전달할 수 있습니다 (예 : 원하는 fmt.Println만큼 많은 인수를 취할 수 있음).

이제 함수를 호출 할 때 ...반대가 수행됩니다. 슬라이스의 압축을 풀고 별도의 인수로 변수를 가변 함수에 전달합니다.

이 라인이하는 일 :

a = append(a[:0], a[1:]...)

본질적으로 :

a = append(a[:0], a[1], a[2])

이제 궁금 할 수도 있습니다.

a = append(a[1:]...)

음의 함수 정의 append

func append(slice []Type, elems ...Type) []Type

따라서 첫 번째 인수는 올바른 유형의 슬라이스 여야하고 두 번째 인수는 가변적이므로 빈 슬라이스를 전달한 다음 나머지 슬라이스의 압축을 풀어 인수를 채 웁니다.


답변

두 가지 옵션이 있습니다.

A : 배열 순서 유지에 관심이 있습니다.

a = append(a[:i], a[i+1:]...)
// or
a = a[:i+copy(a[i:], a[i+1:])]

B : 당신은 질서를 유지하는 것에 신경 쓰지 않는다 (아마 더 빠를 것이다) :

a[i] = a[len(a)-1] // Replace it with the last one. CAREFUL only works if you have enough elements.
a = a[:len(a)-1]   // Chop off the last one.

배열이 포인터 인 경우 메모리 누수에 대한 영향을 보려면 링크를 참조하십시오.

https://github.com/golang/go/wiki/SliceTricks


답변

[a:]-, [:b]-및 -표시 의 색인 [a:b]을 요소 색인으로 생각하는 대신 요소 주변 및 사이의 간격의 0색인으로 생각하십시오 0.

여기에 이미지 설명을 입력하십시오

그냥 파란색 숫자를 보면, 그것은에 무슨 일이 일어나고 있는지 볼 훨씬 쉽게 : [0:3]은 분리 장치의 모든 것을 [3:3]비어 있고 [1:2]얻을 것이다 {"B"}. 그러면 [a:]짧은 버전 [a:len(arrayOrSlice)], [:b]짧은 버전 [0:b][:]짧은 버전이 [0:len(arrayOrSlice)]있습니다. 후자는 일반적으로 필요할 때 배열을 슬라이스로 변환하는 데 사용됩니다.


답변

… 가변 인수에 대한 구문입니다.

나는 그것이 []Type)append 함수와 같이 slice ( )를 사용하여 컴파일러에 의해 구현되었다고 생각합니다 .

func append(slice []Type, elems ...Type) []Type

“append”에서 “elems”를 사용할 때 실제로는 slice ([] type)입니다. ” a = append(a[:0], a[1:]...)“는 ” a = append(a[0:0], a[1:])“을 의미합니다

a[0:0] 아무것도없는 슬라이스입니다

a[1:] “Hello2 Hello3″입니다.

이것이 작동하는 방법입니다


답변

허용되는 답변 솔루션으로 색인이 범위를 벗어났습니다. 이유 : 범위 시작시 값을 하나씩 반복하지 않고 인덱스별로 반복합니다. 슬라이스가 범위 내에있는 동안 슬라이스를 수정하면 문제가 발생할 수 있습니다.

기존 답변 :

chars := []string{"a", "a", "b"}

for i, v := range chars {
    fmt.Printf("%+v, %d, %s\n", chars, i, v)
    if v == "a" {
        chars = append(chars[:i], chars[i+1:]...)
    }
}
fmt.Printf("%+v", chars)

예상 :

[a a b], 0, a
[a b], 0, a
[b], 0, b
Result: [b]

실제 :

// Autual
[a a b], 0, a
[a b], 1, b
[a b], 2, b
Result: [a b]

올바른 방법 (솔루션) :

chars := []string{"a", "a", "b"}

for i := 0; i < len(chars); i++ {
    if chars[i] == "a" {
        chars = append(chars[:i], chars[i+1:]...)
        i-- // form the remove item index to start iterate next item
    }
}

fmt.Printf("%+v", chars)

출처 : https://dinolai.com/notes/golang/golang-delete-slice-item-in-range-problem.html


답변

golang의 위키에서는 슬라이스에서 요소 삭제를 포함하여 슬라이스에 대한 몇 가지 트릭을 보여줍니다.

링크 : 여기에 링크 설명을 입력하십시오

예를 들어 a는 숫자 i 요소를 삭제하려는 슬라이스입니다.

a = append(a[:i], a[i+1:]...)

또는

a = a[:i+copy(a[i:], a[i+1:])]


답변