Search code examples
gogo-map

Deleting multiple values from a map in Go at the same time within a loop


I'm trying to delete multiple values from my map[string][]interface{}

I am using the strings.Split function to separate each value i wish to delete, and then looping through them.

I have managed to get it so i can delete index values 0 and 1, however, 1,2 would delete index value 1, but error on index 2.

I have also managed to get it to delete a single value

My thought process was that if I can get it to delete just one value (any index i enter, inc first and last index), then i could use a loop to loop through, and delete the rest.

Everything is stored in the below:

package db

var DataStore map[string][]interface{}

The function

func HandleDelete(w http.ResponseWriter, k, v string) {

It takes the value you wish to delete in as a parameter (and the key, but that's fully functional)

The block of code the issue resides in

The loop starts at the end of the map slice, so when you remove index value 5 for example, 4 is still 4. Whereas if I go the other way, if i delete 5, 6 then becomes index 5. So 5,6 being deleted would effectively mean 5,7 is being deleted.

for i := len(db.DataStore) - 1; i >= 0; i-- {
        for _, idxvalue := range values {
            val, err := strconv.Atoi(idxvalue)

            if err != nil {
                log.Fatal(err)
                return
            }

            dbval := db.DataStore[k][val]

            if i == val {
                if len(db.DataStore[k])-1 == i { //the length goes 1,2,3,4... the index goes 0,1,2,3 - therefore length -1, would be 3 - deletes the last index value
                    db.DataStore[k] = db.DataStore[k][:i]
                } else { //delete everything else
                    db.DataStore[k] = append(db.DataStore[k][:i], db.DataStore[k][i+1:]...)
                }
                //when you delete the last value in that key, delete the key.
                /*if len(db.DataStore[k]) == 0 {
                    delete(db.DataStore, k)
                }*/
                fmt.Fprintf(w, "Key: %v, Value: %v was deleted successfully", k, dbval)
            }
        }
    }

I have tried both loops as below:

for i := len(db.DataStore) - 1; i >= 0; i-- {

Of course the reason the below didn't work, is because you're getting the length, before the loop (in the func body) which won't change after each iteration.

idx := len(db.DataStore) - 1

    for i := idx; i >= 0; i-- {

The below code is to delete the index entered (this works with a single value)

if len(db.DataStore[k])-1 == i { //the length goes 1,2,3,4... the index goes 0,1,2,3 - therefore length -1, would be 3 - deletes the last index value

                    db.DataStore[k] = db.DataStore[k][:i]
                } else { //delete everything else
                    db.DataStore[k] = append(db.DataStore[k][:i], db.DataStore[k][i+1:]...)
                }

I expect the out put of '2,1' to delete index 1 and 2, but the actual input is that it just deletes index 1.


Solution

  • For example,

    package main
    
    import "fmt"
    
    // Delete m k v elements indexed by d.
    func deleteMKVD(m map[string][]interface{}, k string, d []int) {
        v, ok := m[k]
        if !ok {
            return
        }
        for _, i := range d {
            if 0 <= i && i < len(v) {
                v[i] = nil
            }
        }
        lw := 0
        for i := range v {
            if v[i] != nil {
                lw++
            }
        }
        if lw == 0 {
            delete(m, k)
            return
        }
        w := make([]interface{}, 0, lw)
        for i := range v {
            if v[i] != nil {
                w = append(w, v[i])
            }
        }
        m[k] = w
    }
    
    func main() {
        m := map[string][]interface{}{
            "k0": {"v0", "v1", "v2", "v3"},
        }
        fmt.Println(m)
        deleteMKVD(m, "k0", []int{0, 3})
        fmt.Println(m)
        deleteMKVD(m, "k0", []int{1, 0})
        fmt.Println(m)
    }
    

    Playground: https://play.golang.org/p/biEAxthTaj8

    Output:

    map[k0:[v0 v1 v2 v3]]
    map[k0:[v1 v2]]
    map[]