跳到主要内容

Golang 中指定 key 合并数组并去重

· 阅读需 2 分钟
wen

问题

有 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}]
}
Loading Comments...