Delete slice element inside a for

The idiomatic method of removing an element ifrom a slice a, preserving the order, is as follows:

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

I was wondering what would be the best way to do this inside the loop. As far as I understand, it is impossible to use it within a range:

for i := range a { // BAD
    if conditionMeets(a[i]) {
        a = append(a[:i], a[i+1:]...)
    }
}

However, you can use len(a). [EDIT: this does not work, see the answers below]

for i := 0; i < len(a); i++ {
    if conditionMeets(a[i]) {
        a = append(a[:i], a[i+1:]...)
    }
}

Is there a better or more idiomatic way than using lenor append?

+5
source share
1 answer

. , . , , () , , .

2 , , , .

, , ! : , "a":

func conditionMeets(s string) bool {
    return strings.HasPrefix(s, "a")
}

( Go):

a := []string{"abc", "bbc", "aaa", "aoi", "ccc"}
for i := 0; i < len(a); i++ {
    if conditionMeets(a[i]) {
        a = append(a[:i], a[i+1:]...)
        i--
    }
}
fmt.Println(a)

:

[bbc ccc]

: , " " .

a := []string{"abc", "bbc", "aaa", "aoi", "ccc"}
for i := len(a) - 1; i >= 0; i-- {
    if conditionMeets(a[i]) {
        a = append(a[:i], a[i+1:]...)
    }
}
fmt.Println(a)

.

"" , , (append() ). : 1000 ; 999 . : 2 (a[:i], a[i+1:]), a a ( append()). .

:

a := []string{"abc", "bbc", "aaa", "aoi", "ccc"}
b := make([]string, len(a))
copied := 0
for _, s := range(a) {
    if !conditionMeets(s) {
        b[copied] = s
        copied++
    }
}
b = b[:copied]
fmt.Println(b)

, , ( ) . range. a, a: a = b[:copied].

.

( )

" " , 2 ( ) .

, , , GC . , .

:

a := []string{"abc", "bbc", "aaa", "aoi", "ccc"}
copied := 0
for i := 0; i < len(a); i++ {
    if !conditionMeets(a[i]) {
        a[copied] = a[i]
        copied++
    }
}
for i := copied; i < len(a); i++ {
    a[i] = "" // Zero places of removed elements (allow gc to do its job)
}
a = a[:copied]
fmt.Println(a)

. Go.

+9

Source: https://habr.com/ru/post/1614248/


All Articles