4 回答
TA贡献1998条经验 获得超6个赞
问题中的代码已经差不多了。当在 中找到匹配元素时unique,用当前值覆盖该元素:
func unique(sample []samplestruct) []samplestruct {
var unique []samplestruct
sampleLoop:
for _, v := range sample {
for i, u := range unique {
if v.value1 == u.value1 && v.value2 == u.value2 && v.value3 == u.value3 {
unique[i] = v
continue sampleLoop
}
}
unique = append(unique, v)
}
return unique
}
其他答案中显示的基于地图的方法可能更合适,具体取决于数据集的大小和幸存元素的数量。这是地图方法的正确实现:
func unique(sample []samplestruct) []samplestruct {
var unique []samplestruct
type key struct{ value1, value2, value3 string }
m := make(map[key]int)
for _, v := range sample {
k := key{v.value1, v.value2, v.value3}
if i, ok := m[k]; ok {
// Overwrite previous value per requirement in
// question to keep last matching value.
unique[i] = v
} else {
// Unique key found. Record position and collect
// in result.
m[k] = len(unique)
unique = append(unique, v)
}
}
return unique
}
TA贡献1982条经验 获得超2个赞
很好的小练习,这是一个解决方案,我将在下面解释:
package main
import "fmt"
func main() {
all := []person{
{"ram", "rahim", "india", "34", "india"},
{"ram", "rahim", "india", "38", "America"},
{"ram", "rahim", "india", "40", "Jamica"},
{"amit", "rawat", "bangladesh", "35", "hawai"},
{"amit", "rawat", "bangladesh", "36", "india"},
}
var deduped []person
// add the last occurrence always
for i := len(all) - 1; i >= 0; i-- {
if !contains(deduped, all[i]) {
// "append" to the front of the array
deduped = append([]person{all[i]}, deduped...)
}
}
for _, x := range deduped {
fmt.Println(x)
}
}
type person [5]string
func eq(a, b person) bool {
return a[0] == b[0] && a[1] == b[1] && a[2] == b[2]
}
func contains(list []person, x person) bool {
for i := range list {
if eq(x, list[i]) {
return true
}
}
return false
}
我们向后遍历输入数组,以捕获多个相等项中的最后一个。然后我们想将该项目附加到数组的后面deduped。这就是为什么我们恢复追加操作,创建一个新的临时单项person切片并将前一个切片附加到其中。
从效率角度来看,该解决方案有一些缺点,附加到单项切片将使用 O(n²) 空间,因为它每次都会生成一个新切片,预先分配一个 数组,附加到它,然后反转它可以len(all)解决那个问题。
如果您对无数次执行此操作,可能会出现的第二个性能问题person是contains程序的 O(n²) 查找函数。这可以通过map[person]bool.
TA贡献1898条经验 获得超8个赞
也许你应该在这里使用一个映射,使用重要的值作为键,当你遇到重复并检查键时,你替换映射中的值。
unique
目前,如果您之前没有遇到过这些值,则将其添加到数组中,然后如果您在数组中遇到该值,则跳过它。这就是为什么您只添加每个结构的第一次遇到,这与您想要的相反。
您可以将映射的键生成为重要值(1 到 3)的串联,或者使用三个值的结构作为键,并为每个项目构建新的键结构,然后在地图。
使用映射也比数组具有更高的性能,因为在映射中查找比unique
每次迭代数组要快得多。
TA贡献1895条经验 获得超3个赞
使用地图。首先扫描列表并设置一个映射,其中前 3 个值作为映射的键。每个键的映射值将是最后找到的
然后在地图上行走,它将被设置为正确的值
package main
import (
"fmt"
"strings"
)
type samplestruct struct {
value1 string
value2 string
value3 string
value4 string
value5 string
}
func mkey(x samplestruct) string {
return strings.Join([]string{x.value1, x.value2, x.value3}, "-")
}
func main() {
cm := make(map[string]samplestruct)
exampledata := []samplestruct{samplestruct{"ram", "rahim", "india", "34", "india"},
samplestruct{"ram", "rahim", "india", "38", "America"},
samplestruct{"ram", "rahim", "india", "40", "Jamica"},
samplestruct{"amit", "rawat", "bangladesh", "35", "hawai"},
samplestruct{"amit", "rawat", "bangladesh", "36", "india"}}
for _, x := range exampledata {
k := mkey(x)
cm[k] = x
}
for x := range cm {
fmt.Println(cm[x])
}
}
https://play.golang.org/p/ITD0VjhFQEk
- 4 回答
- 0 关注
- 160 浏览
添加回答
举报