如何从切片中删除重复的项?

huangapple go评论93阅读模式
英文:

How to delete duplicates of an item from a slice?

问题

我正在编写一个命令行工具,用于从文本文件中删除对等体。

这是文本文件。在代码中的引用是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"
}

]

使用用户提供的PeerID和Address创建对等体对象,如下所示:

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

目标是删除所有包含用户提供的Address和PeerID的cfg.Bootstrap中的对等体。

//多次迭代对等体列表,以便删除所有匹配项
for i := range cfg.Bootstrap {

//迭代对等体列表
for i, val := range cfg.Bootstrap {
    
    //如果用户提供的PeerID和Address与cfg.Bootstrap中的对等体对象匹配..
    if(val.PeerID == peer.PeerID && val.Address == peer.Address) {
    				
        //删除该元素
        cfg.Bootstrap = append(cfg.Bootstrap[:i], cfg.Bootstrap[i+1:]...)
    }
}
    		
fmt.Println(i)

}

这个方法是有效的,除非cfg.Bootstrap中的最后一个对等体有一个重复项。如果有重复项,Go会出现错误:

panic: runtime error: slice bounds out of range

我需要让用户能够删除包含最后一个对等体的所有副本。有什么想法吗?

英文:

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?

答案1

得分: 9

基本思想是将不等于对等方的值复制到切片的开头,并在完成后修剪多余的部分。

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]
英文:

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]

答案2

得分: 0

另一种方法(如果你有这个选项)是先排序,然后去除重复项。例如,对于字符串:

strs = []string{"a", "b", "c", "d", "e", "b", "a", "e", "e", "d"}
sort.Strings(strs)

var last string
first_item := true
dedupped := []string{}
for _, s := range strs {
	if first_item {
		dedupped = append(dedupped, s)
		first_item = false
	} else {
		if s != last {
			dedupped = append(dedupped, s)
		}
	}
	last = s
}

另一种方法(如果您有此选项)是先对字符串进行排序,然后删除重复项。例如:

strs = []string{"a", "b", "c", "d", "e", "b", "a", "e", "e", "d"}
sort.Strings(strs)

var last string
first_item := true
dedupped := []string{}
for _, s := range strs {
	if first_item {
		dedupped = append(dedupped, s)
		first_item = false
	} else {
		if s != last {
			dedupped = append(dedupped, s)
		}
	}
	last = s
}
英文:

Another approach (if you have the option) is to first sort, then remove duplicates. Eg with strings;

strs = []string{"a", "b", "c", "d", "e", "b", "a", "e", "e", "d"}
sort.Strings(strs)

var last string
first_item := true
dedupped := []string{}
for _, s := range strs {
	if first_item {
		dedupped = append(dedupped, s)
		first_item = false
	} else {
		if s != last {
			dedupped = append(dedupped, s)
		}
	}
	last = s
}

答案3

得分: 0

将你的结构体编组成 JSON,然后将其转换为字符串。

data, _ := json.Marshal(yourStruct)
dup := make(map[string]bool)
dup[string(data)] = true

现在可以使用这个 dup 来过滤掉重复项。

英文:

Marshal your struct into json and then stringify

data, _ := json.Marshal(yourStruct)
dup := make(map[string]bool)
dup[string(data)] = true

Now use this dup to filter out duplicates

huangapple
  • 本文由 发表于 2014年10月3日 10:58:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/26172673.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定