62 lines
1.3 KiB
Go
62 lines
1.3 KiB
Go
package fields
|
|
|
|
import "sort"
|
|
|
|
type Fields []Field
|
|
|
|
// Merge merges other with the current set, replacing any matching keys from other.
|
|
func (fs *Fields) Merge(other Fields) {
|
|
var list []Field
|
|
i, j := 0, 0
|
|
for i < len(*fs) && j < len(other) {
|
|
if (*fs)[i].key < other[j].key {
|
|
list = append(list, (*fs)[i])
|
|
i++
|
|
} else if (*fs)[i].key > other[j].key {
|
|
list = append(list, other[j])
|
|
j++
|
|
} else {
|
|
// equal, then "other" replaces existing key
|
|
list = append(list, other[j])
|
|
i++
|
|
j++
|
|
}
|
|
}
|
|
|
|
if i < len(*fs) {
|
|
list = append(list, (*fs)[i:]...)
|
|
} else if j < len(other) {
|
|
list = append(list, other[j:]...)
|
|
}
|
|
|
|
*fs = list
|
|
}
|
|
|
|
// New creates a new set of fields, sorted by Key.
|
|
// Duplicate keys are removed.
|
|
func New(args ...Field) Fields {
|
|
fields := Fields(args)
|
|
sort.Slice(fields, func(i, j int) bool {
|
|
return fields[i].key < fields[j].key
|
|
})
|
|
|
|
// deduplicate
|
|
// loop invariant: fields[:i] has no duplicates
|
|
for i := 0; i < len(fields)-1; i++ {
|
|
j := i + 1
|
|
// find all duplicate keys
|
|
for j < len(fields) && fields[i].key == fields[j].key {
|
|
j++
|
|
}
|
|
|
|
d := (j - 1) - i // number of duplicate keys
|
|
if d > 0 {
|
|
// copy over duplicate keys in order to maintain loop invariant
|
|
copy(fields[i+1:], fields[j:])
|
|
fields = fields[:len(fields)-d]
|
|
}
|
|
}
|
|
|
|
return fields
|
|
}
|