merge.go

 1// Copyright 2020 Jebbs. All rights reserved.
 2// Use of this source code is governed by MIT
 3// license that can be found in the LICENSE file.
 4
 5package rule
 6
 7import "github.com/qjebbs/go-jsons/merge"
 8
 9func mergeByFields(s []interface{}, fields []Field) ([]interface{}, error) {
10	if len(s) == 0 || len(fields) == 0 {
11		return s, nil
12	}
13	// from: [a,"",b,"",a,"",b,""]
14	// to: [a,"",b,"",merged,"",merged,""]
15	merged := &struct{}{}
16	for i, item1 := range s {
17		map1, ok := item1.(map[string]interface{})
18		if !ok {
19			continue
20		}
21		tags1 := getTags(map1, fields)
22		if len(tags1) == 0 {
23			continue
24		}
25		for j := i + 1; j < len(s); j++ {
26			map2, ok := s[j].(map[string]interface{})
27			if !ok {
28				continue
29			}
30			tags2 := getTags(map2, fields)
31			if !matchTags(tags1, tags2) {
32				continue
33			}
34			s[j] = merged
35			err := merge.Maps(map1, map2)
36			if err != nil {
37				return nil, err
38			}
39		}
40	}
41	// remove merged
42	ns := make([]interface{}, 0)
43	for _, item := range s {
44		if item == merged {
45			continue
46		}
47		ns = append(ns, item)
48	}
49	return ns, nil
50}
51
52func matchTags(a, b []string) bool {
53	for _, tag1 := range a {
54		for _, tag2 := range b {
55			if tag1 == tag2 {
56				return true
57			}
58		}
59	}
60	return false
61}
62
63func getTags(v map[string]interface{}, fields []Field) []string {
64	tags := make([]string, 0, len(fields))
65	for _, field := range fields {
66		value, ok := v[field.Key]
67		if !ok {
68			continue
69		}
70		if tag, ok := value.(string); ok && tag != "" {
71			tags = append(tags, tag)
72		}
73	}
74	return tags
75}