24

Problem

I have array of structs:

type Config struct {
  Applications []Application
}

Note: Config - is a struct for json.Decode.

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

In loop I have some condition and element deletion by key.

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
}

But always I have "out of range" error. What is the best way to delete element by key from array of structs?

5 Answers 5

47

Quoting from the Slice Tricks page deleting the element at index i:

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

Note that if you plan to delete elements from the slice you're currently looping over, that may cause problems. And it does if the element you remove is the current one (or a previous element already looped over) because after the deletion all subsequent elements are shifted, but the range loop does not know about this and will still increment the index and you skip one element.

You can avoid this by using a downward loop:

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:]...)
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

@Michael The ... tells that you have a slice which you want to pass to be the value of the variadic parameter. append() has a variadic parameter which is normally called by enumerating the elements, but in this case we call it by having the elements in a slice and passing that slice, and we want the elements of the slice to be the values of the variadic parameter (and we don't want the slice itself to be a single element for the variadic parameter).
break from the loop, since you want to delete a single element ?
7

You are getting this error because you are doing a loop over a slice with an inital range of X length that became X-n because you remove some elements during loop.

If you want to delete an item at a specific index from a slice, you can do it this way:

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

Comments

4

This question is a bit older but I haven't found another answer on StackOverflow which mentions the following trick from the Slice Tricks to filter a list:

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

So in this case a function which deletes certain elements could look like this:

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

Comments

1

I think the simple way is

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

here is... https://play.golang.org/p/pK3B5Mii9k

Comments

0

To remove a particular slice from a struct we need to run a for-loop to find that particular slice and delete it

for example:

type variable struct {
Id      int    `json:"id"`
Message string `json:"message"`
}

var mssg = []variable{
{Id: 1, Message: "success"},
{Id: 2, Message: "failed"}
}
for i, a := range mssg {
    if a.Message == "success" {
        mssg = append(mssg[:i], mssg[i+1:]...)
        fmt.Println(mssg)
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.