2015-03-12 36 views
13

ProblemaCome rimuovere elemento dell'array struct in loop in golang

ho array di struct:

type Config struct { 
    Applications []Application 
} 

Nota: Config - è una struct per json.Decode.

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

In Anello Ho alcune condizioni e elemento eliminazione dalla chiave.

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 
} 

Ma sempre ho errore "fuori intervallo". Qual è il modo migliore per cancellare elemento per chiave da una matrice di strutture?

risposta

33

Citando dalla pagina Slice Tricks eliminare l'elemento in corrispondenza dell'indice i:

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

Si noti che se avete intenzione di eliminare gli elementi dalla fetta si sta loop sopra, che possono causare problemi. E lo fa se l'elemento che rimuovi è quello corrente (o un elemento precedente già loopato) perché dopo l'eliminazione tutti gli elementi successivi vengono spostati, ma il ciclo range non lo sa e continuerà ad incrementare l'indice e tu salterai uno elemento.

È possibile evitare questo utilizzando un ciclo al ribasso:

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

Qual è il ... nel comando append per? – Michael

+0

@Michael Il '...' dice che hai una sezione che vuoi passare per essere il valore del parametro _variadic_. ['append()'] (https://golang.org/pkg/builtin/#append) ha un parametro variadic che normalmente viene chiamato _enumerating_ gli elementi, ma in questo caso lo chiamiamo _having_ gli elementi in una slice e _passando_ quella slice, e vogliamo che gli elementi della slice siano i valori del parametro variadic (e non vogliamo che la slice stessa sia un singolo elemento per il parametro variadic). – icza

3

State ottenendo questo errore perché si sta facendo un loop su una fetta con una gamma inital di lunghezza X che è diventato Xn perché si rimuove alcuni elementi durante il ciclo.

Se si desidera eliminare un elemento ad un indice specifico da una fetta, si può fare in questo modo:

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

Questa domanda è un po 'più vecchio, ma non ho trovato un'altra risposta su StackOverflow che cita il seguente trucco dal Slice Tricks per filtrare un elenco:

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

Quindi in questo caso di una funzione che cancella alcuni elementi potrebbe assomigliare a questo:

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

Penso che il modo più semplice è

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++ 
    } 

qui è ... https://play.golang.org/p/pK3B5Mii9k

Problemi correlati