web-dev-qa-db-fra.com

Comment supprimer un élément de struct array en boucle dans golang

Problème

J'ai un tableau de structs:

type Config struct {
  Applications []Application
}

Remarque: Config - est une structure pour json.Decode.

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

En boucle, j'ai une condition et la suppression d'éléments par clé.

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
}

Mais j'ai toujours une erreur "hors de portée". Quel est le meilleur moyen de supprimer élément par clé d'un tableau de structures?

15
Alex Pliutau

Citant depuis la page Slice Tricks supprimant l’élément à l’index i:

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

Notez que si vous envisagez de supprimer des éléments de la tranche que vous êtes en train de boucler, cela peut poser problème. Et c'est le cas si l'élément que vous supprimez est l'élément actuel (ou un élément précédent déjà bouclé) car après la suppression, tous les éléments suivants sont décalés, mais la boucle range ne le sait pas et incrémente toujours l'index élément.

Vous pouvez éviter cela en utilisant une boucle descendante:

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:]...)
    }
}
35
icza

Cette question est un peu plus ancienne mais je n'ai pas trouvé d'autre réponse sur StackOverflow qui mentionne l'astuce suivante du Slice Tricks pour filtrer une liste: 

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

Donc, dans ce cas, une fonction qui supprime certains éléments pourrait ressembler à ceci:

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

Vous obtenez cette erreur parce que vous effectuez une boucle sur une tranche avec une plage initiale de longueur X devenue X-n car vous supprimez certains éléments pendant la boucle.

Si vous souhaitez supprimer un élément à un index spécifique d'une tranche, vous pouvez le faire comme suit:

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

Je pense que la manière simple est 

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

voici ... https://play.golang.org/p/pK3B5Mii9k

1
Martin Prestone