Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delete duplicates of an item from a slice?

Tags:

go

I'm writing a command line tool that will delete peers from a text file.

This is the text file. Its reference in code is cfg.Bootstrap

 "Bootstrap": [
{
  "Address": "/ip4/162.243.139.64/tcp/5001",
  "PeerID": "QmXZPT1SLcczjNSLnSCsQBWwbosKjrDRo122Ys8ajKoQXQ"
},
{
  "Address": "/ip4/162.243.139.64/tcp/5001",
  "PeerID": "QmXZPT1SLcczjNSLnSCsQBWwbosKjrDRo122Ys8ajKoQXA"
},
{
  "Address": "/ip4/162.243.139.64/tcp/5001",
  "PeerID": "QmXZPT1SLcczjNSLnSCsQBWwbosKjrDRo122Ys8ajKoQXQ"
},
{
  "Address": "/ip4/162.243.139.64/tcp/5001",
  "PeerID": "QmXZPT1SLcczjNSLnSCsQBWwbosKjrDRo122Ys8ajKoQXA"
}

]

The peer object is created using a user supplied PeerID and Address. It looks like this

peer := config.BootstrapPeer{
                Address: address,
                PeerID:  pID,
            }

The goal is to remove all peers cfg.Bootstrap that contain the user supplied Address and PeerID

   //iterate through the list of peers multiple times so that we delete all matches
   for i := range cfg.Bootstrap {

            //iterate through the list of peers
            for i, val := range cfg.Bootstrap {

                //if the user supplied PeerID and Address match a Peer object in cfg.Bootstrap..
                if(val.PeerID == peer.PeerID && val.Address == peer.Address) {

                //remove that element 
                    cfg.Bootstrap = append(cfg.Bootstrap[:i], cfg.Bootstrap[i+1:]...)
                }

            }

                fmt.Println(i)

    }

This works UNLESS the last peer in cfg.Bootstrap has a duplicate. If it has a duplicate then Go panics with

panic: runtime error: slice bounds out of range

I need to make it so the user can delete all copies of a peer that include the last peer. Any ideas?

like image 227
sourcerer Avatar asked Jan 09 '23 16:01

sourcerer


1 Answers

The basic idea is to copy values != to peer to the beginning of the slice and trim the excess when done.

i := 0
for _, v := range cfg.Bootstrap {
   if v.PeerId == peer.PeerId && v.Address == peer.Address {
      continue
   }
   cfg.Bootstrap[i] = v
   i++
}
cfg.Bootstrap = cfg.Bootstrap[:i]
like image 193
Simon Fox Avatar answered May 30 '23 17:05

Simon Fox