问题
有 2 个数组,互相可能有重复的元素,如何合并这两个数组并去重?
比如有两个数组:
type User struct {
ID int // ID 作为唯一标识 (ID相同则认为是同一个元素)
Name string
}
old := []User{
{ID: 1, Name: "a"}, // only in old
{ID: 2, Name: "b"}, // 重复
}
new := []User{
{ID: 2, Name: "c"}, // 重复
{ID: 3, Name: "d"}, // only in new
}
合并后的结果应该是:
c := []User{
{ID: 1, Name: "a"}, // only in old
{ID: 2, Name: "c"}, // 重复 (保留 new 中的)
{ID: 3, Name: "d"}, // only in new
}
解决方案(一般化)
package main
import "fmt"
type User struct {
ID int
Name string
}
// contains Check if an element exists in a slice.
// keyFunc is used to uniquely identify the elements.
func contains(slice []any, item any, keyFunc func(any) any) bool {
for _, element := range slice {
if keyFunc(element) == keyFunc(item) {
return true
}
}
return false
}
// mergeSlices Merges two slices and removes duplicates.
//
// keyFunc is used to uniquely identify the elements.
// if an element exists in both old and new, the element in new takes precedence.
// old and new are assumed to have no duplicate elements.
// The order is not guaranteed.
func MergeSlices(old, new []any, keyFunc func(any) any) []any {
var merged []any
// copy new to merged
merged = append(merged, new...)
for _, item := range old {
if !contains(merged, item, keyFunc) {
merged = append(merged, item)
}
}
return merged
}
func main() {
old := []any{
User{ID: 1, Name: "a"},
User{ID: 2, Name: "b"}, // 重複
}
new := []any{
User{ID: 2, Name: "c"}, // 重複
User{ID: 3, Name: "d"},
}
mergedUsers := MergeSlices(old, new, func(item any) any {
return item.(User).ID
})
fmt.Printf("Merged Users:%+v", mergedUsers) // Merged Users:[ {ID:1 Name:a} {ID:2 Name:c} {ID:3 Name:d}]
}