2015-03-12 19 views
13

ProblemJak usunąć element tablicy struct w pętli w golang

Mam tablicę kodowanym:

type Config struct { 
    Applications []Application 
} 

Uwaga: config - to struktura dla json.Decode.

config = new(Config) 
_ = decoder.Decode(&config) 

W pętli mam pewne usunięcie warunku i elementu za pomocą klucza.

for i, application := range config.Applications { 
    if i == 1 { 
    config.Applications = _removeApplication(i, config.Applications) 
    } 
} 

func _removeApplication(i int, list []Application) []Application { 
    if i < len(list)-1 { 
    list = append(list[:i], list[i+1:]...) 
    } else { 
    log.Print(list[i].Name) 
    list = list[:i] 
    } 

    return list 
} 

Ale zawsze mam błąd "poza zasięgiem". Jaki jest najlepszy sposób na usunięcie elementu za pomocą klucza z tablicy struktur?

Odpowiedz

33

Cytując ze strony Slice Tricks usuwanego elementu o indeksie i:

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

Pamiętaj, że jeśli masz zamiar usunąć elementy z plasterka aktualnie zapętlenie nad, które mogą powodować problemy. I działa, jeśli element, który usuniesz, jest bieżący (lub poprzedni element już zapętlony), ponieważ po usunięciu wszystkie kolejne elementy są przesunięte, ale pętla range nic o tym nie wie i nadal będzie zwiększać indeks i pominiesz jeden element.

Można tego uniknąć stosując pętlę w dół:

for i := len(config.Applications) - 1; i >= 0; i-- { 
    application := config.Applications[i] 
    // Condition to decide if current element has to be deleted: 
    if haveToDelete { 
     config.Applications = append(config.Applications[:i], 
       config.Applications[i+1:]...) 
    } 
} 
+0

... Co jest w poleceniu dopisywania do? – Michael

+0

@Michael "..." mówi, że masz kawałek, który chcesz przekazać jako wartość parametru _variadic_. ['append()'] (https://golang.org/pkg/builtin/#append) ma parametr variadic, który jest zwykle wywoływany przez _enumerowanie_ elementów, ale w tym przypadku wywołujemy go przez _having_ elementy w plasterku i _passing_, który chcemy wyciąć, a my chcemy, aby elementy wycinka były wartościami parametru variadic (i nie chcemy, aby sam plasterek był pojedynczym elementem dla parametru variadic). – icza

3

Otrzymujesz ten błąd, ponieważ robisz pętlę nad plasterek z przeczuciom zakresie długości X, który stał Xn bo usunąć niektóre elementy podczas pętli.

Jeśli chcesz usunąć element w określonym indeksie z plasterka, możesz zrobić to w ten sposób:

sliceA = append(sliceA[:indexOfElementToRemove], sliceA[indexOfElementToRemove+1:]...) 
3

to pytanie jest nieco starszy, ale nie znalazłem inną odpowiedź na StackOverflow, które wymieniono następujące sztuczka z Slice Tricks filtrować listę:

b := a[:0] 
for _, x := range a { 
    if f(x) { 
     b = append(b, x) 
    } 
} 

Więc w tym przypadku funkcja, która usuwa niektóre elementy mogłyby wyglądać następująco:

func removeApplications(apps []Applications) []Applications { 
    filteredApps := apps[:0] 
    for _, app := apps { 
     if !removeApp { 
      filteredApps = append(filteredApps, app) 
     } 
    } 
    return filteredApps 
} 
1

myślę, że prostym sposobem jest

var (
    slice = []int{1,2,3,4,5} 
    pos int 
) 
    for _, i := range slice { 
     if i == 3 { 
      slice = append(slice[:pos], slice[pos+1:]...) 
      if pos > 0 { 
       pos = pos - 1 
      } 
      continue 
     } 
     pos++ 
    } 

tutaj jest ... https://play.golang.org/p/pK3B5Mii9k