sort.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 (
 8	"math"
 9	"sort"
10)
11
12type meta struct {
13	index int
14	order float64
15	value interface{}
16}
17
18// sortByFields sort slice elements by specified fields
19func sortByFields(slice []interface{}, fields []Field) {
20	if len(slice) == 0 || len(fields) == 0 {
21		return
22	}
23	metas := make([]meta, len(slice))
24	for i, v := range slice {
25		metas[i] = meta{
26			index: i,
27			order: getOrder(v, fields),
28			value: v,
29		}
30	}
31	sort.Slice(
32		metas,
33		func(i, j int) bool {
34			if metas[i].order != metas[j].order {
35				return metas[i].order < metas[j].order
36			}
37			return metas[i].index < metas[j].index
38		},
39	)
40	for i, m := range metas {
41		slice[i] = m.value
42	}
43}
44
45func getOrder(v interface{}, fields []Field) float64 {
46	m, ok := v.(map[string]interface{})
47	if !ok {
48		return 0
49	}
50	hasField := false
51	min := math.Inf(1)
52	for _, field := range fields {
53		value, ok := m[field.Key]
54		if !ok || value == nil {
55			continue
56		}
57		hasField = true
58		var num float64
59		switch v := value.(type) {
60		case float64:
61			num = v
62		case float32:
63			num = float64(v)
64		case int:
65			num = float64(v)
66		case int8:
67			num = float64(v)
68		case int16:
69			num = float64(v)
70		case int32:
71			num = float64(v)
72		case int64:
73			num = float64(v)
74		case uint:
75			num = float64(v)
76		case uint8:
77			num = float64(v)
78		case uint16:
79			num = float64(v)
80		case uint32:
81			num = float64(v)
82		case uint64:
83			num = float64(v)
84		default:
85			num = 0
86		}
87		if num < min {
88			min = num
89		}
90	}
91	if !hasField {
92		return 0
93	}
94	return min
95}