-
Notifications
You must be signed in to change notification settings - Fork 2
/
collection.go
113 lines (101 loc) · 2.98 KB
/
collection.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//-----------------------------------------------------------------------------
// Copyright (c) 2022-present Detlef Stern
//
// This file is part of Zettelstore.
//
// Zettelstore is licensed under the latest version of the EUPL (European Union
// Public License). Please see file LICENSE.txt for your rights and obligations
// under this license.
//
// SPDX-License-Identifier: EUPL-1.2
// SPDX-FileCopyrightText: 2022-present Detlef Stern
//-----------------------------------------------------------------------------
package meta
import "sort"
// Arrangement stores metadata within its categories.
// Typecally a category might be a tag name, a role name, a syntax value.
type Arrangement map[string][]*Meta
// CreateArrangement by inspecting a given key and use the found
// value as a category.
func CreateArrangement(metaList []*Meta, key string) Arrangement {
if len(metaList) == 0 {
return nil
}
descr := Type(key)
if descr == nil {
return nil
}
if descr.IsSet {
return createSetArrangement(metaList, key)
}
return createSimplearrangement(metaList, key)
}
func createSetArrangement(metaList []*Meta, key string) Arrangement {
a := make(Arrangement)
for _, m := range metaList {
if vals, ok := m.GetList(key); ok {
for _, val := range vals {
a[val] = append(a[val], m)
}
}
}
return a
}
func createSimplearrangement(metaList []*Meta, key string) Arrangement {
a := make(Arrangement)
for _, m := range metaList {
if val, ok := m.Get(key); ok && val != "" {
a[val] = append(a[val], m)
}
}
return a
}
// Counted returns the list of categories, together with the number of
// metadata for each category.
func (a Arrangement) Counted() CountedCategories {
if len(a) == 0 {
return nil
}
result := make(CountedCategories, 0, len(a))
for cat, metas := range a {
result = append(result, CountedCategory{Name: cat, Count: len(metas)})
}
return result
}
// CountedCategory contains of a name and the number how much this name occured
// somewhere.
type CountedCategory struct {
Name string
Count int
}
// CountedCategories is the list of CountedCategories.
// Every name must occur only once.
type CountedCategories []CountedCategory
// SortByName sorts the list by the name attribute.
// Since each name must occur only once, two CountedCategories cannot have
// the same name.
func (ccs CountedCategories) SortByName() {
sort.Slice(ccs, func(i, j int) bool { return ccs[i].Name < ccs[j].Name })
}
// SortByCount sorts the list by the count attribute, descending.
// If two counts are equal, elements are sorted by name.
func (ccs CountedCategories) SortByCount() {
sort.Slice(ccs, func(i, j int) bool {
iCount, jCount := ccs[i].Count, ccs[j].Count
if iCount > jCount {
return true
}
if iCount == jCount {
return ccs[i].Name < ccs[j].Name
}
return false
})
}
// Categories returns just the category names.
func (ccs CountedCategories) Categories() []string {
result := make([]string, len(ccs))
for i, cc := range ccs {
result[i] = cc.Name
}
return result
}