v2 / vlib / arrays / uniq.v
153 lines · 148 sloc · 4.73 KB · c7b7d5f50feb290eadac5ec8e7c9d8a786b657d2
Raw
1module arrays
2
3// uniq filters the adjacent matching elements from the given array.
4// All adjacent matching elements, are merged to their first occurrence,
5// so the output will have no repeating elements.
6// Note: `uniq` does not detect repeats, unless they are adjacent.
7// You may want to call a.sorted() on your array, before passing the result to arrays.uniq().
8// See also arrays.distinct, which is essentially arrays.uniq(a.sorted()) .
9// Example: assert arrays.uniq( []int{} ) == []
10// Example: assert arrays.uniq( [1, 1] ) == [1]
11// Example: assert arrays.uniq( [2, 1] ) == [2, 1]
12// Example: assert arrays.uniq( [5, 5, 1, 5, 2, 1, 1, 9] ) == [5, 1, 5, 2, 1, 9]
13pub fn uniq[T](a []T) []T {
14 mut res := []T{cap: a.len / 10}
15 mut j := -1
16 if a.len > 0 {
17 j = 0
18 res << a[0]
19 }
20 for idx, e in a {
21 if a[j] == e {
22 continue
23 }
24 j = idx
25 res << e
26 }
27 return res
28}
29
30// uniq_only filters the adjacent matching elements from the given array.
31// All adjacent matching elements, are removed.
32// The output will contain only the elements that *did not have* any adjacent matches.
33// Note: `uniq_only` does not detect repeats, unless they are adjacent.
34// You may want to call a.sorted() on your array, before passing the result to arrays.uniq_only().
35// Example: assert arrays.uniq_only( []int{} ) == []
36// Example: assert arrays.uniq_only( [1, 1] ) == []
37// Example: assert arrays.uniq_only( [2, 1] ) == [2, 1]
38// Example: assert arrays.uniq_only( [1, 5, 5, 1, 5, 2, 1, 1, 9] ) == [1, 1, 5, 2, 9]
39pub fn uniq_only[T](a []T) []T {
40 // simple cases:
41 if a.len == 0 {
42 return []
43 }
44 if a.len == 1 {
45 return a.clone()
46 }
47 if a.len == 2 {
48 if a[0] != a[1] {
49 return a.clone()
50 }
51 return []
52 }
53 mut res := []T{cap: a.len / 20}
54 // head element:
55 if a[0] != a[1] {
56 res << a[0]
57 }
58 // middle elements:
59 for idx := 1; idx + 1 < a.len; idx++ {
60 if a[idx - 1] != a[idx] && a[idx + 1] != a[idx] {
61 res << a[idx]
62 }
63 }
64 // tail element:
65 if a[a.len - 2] != a[a.len - 1] {
66 res << a[a.len - 1]
67 }
68 return res
69}
70
71// uniq_only_repeated produces the adjacent matching elements from the given array.
72// Unique elements, with no duplicates are removed.
73// Adjacent matching elements, are reduced to just 1 element per repeat group.
74// Note: `uniq_only_repeated` does not detect repeats, unless they are adjacent.
75// You may want to call a.sorted() on your array, before passing the result to arrays.uniq_only_repeated().
76// Example: assert arrays.uniq_only_repeated( []int{} ) == []
77// Example: assert arrays.uniq_only_repeated( [1, 5] ) == []
78// Example: assert arrays.uniq_only_repeated( [5, 5] ) == [5]
79// Example: assert arrays.uniq_only_repeated( [5, 5, 1, 5, 2, 1, 1, 9] ) == [5, 1]
80pub fn uniq_only_repeated[T](a []T) []T {
81 // simple cases:
82 if a.len == 0 || a.len == 1 {
83 return []
84 }
85 mut res := []T{cap: a.len / 20}
86 loop: for i := 0; i + 1 < a.len; i++ {
87 if a[i] == a[i + 1] {
88 // at least 2 match; find the span length:
89 for j := i + 2; j < a.len; j++ {
90 if a[i] != a[j] {
91 // found the right border of the repeated elements
92 if j - i > 1 {
93 res << a[i]
94 i = j - 1
95 continue loop
96 }
97 }
98 }
99 break
100 }
101 }
102 // tail element:
103 if a[a.len - 2] == a[a.len - 1] {
104 res << a[a.len - 1]
105 }
106 return res
107}
108
109// uniq_all_repeated produces all adjacent matching elements from the given array.
110// Unique elements, with no duplicates are removed.
111// The output will contain all the duplicated elements, repeated just like they were in the original.
112// Note: `uniq_all_repeated` does not detect repeats, unless they are adjacent.
113// You may want to call a.sorted() on your array, before passing the result to arrays.uniq_all_repeated().
114// Example: assert arrays.uniq_all_repeated( []int{} ) == []
115// Example: assert arrays.uniq_all_repeated( [1, 5] ) == []
116// Example: assert arrays.uniq_all_repeated( [5, 5] ) == [5,5]
117// Example: assert arrays.uniq_all_repeated( [5, 5, 1, 5, 2, 1, 1, 9] ) == [5, 5, 1, 1]
118pub fn uniq_all_repeated[T](a []T) []T {
119 // simple cases:
120 if a.len == 0 || a.len == 1 {
121 return []
122 }
123 if a.len == 2 {
124 if a[0] == a[1] {
125 return a.clone()
126 }
127 }
128 mut res := []T{cap: a.len / 20}
129 loop: for i := 0; i + 1 < a.len; i++ {
130 if a[i] == a[i + 1] {
131 res << a[i]
132 for j := i + 1; j < a.len; j++ {
133 if a[i] != a[j] && j - i > 0 {
134 // found the right border of the repeated elements
135 i = j - 1
136 continue loop
137 }
138 res << a[i]
139 }
140 break
141 }
142 }
143 return res
144}
145
146// distinct returns all distinct elements from the given array a.
147// The results are guaranteed to be unique, i.e. not have duplicates.
148// See also arrays.uniq, which can be used to achieve the same goal,
149// but needs you to first sort the array.
150// Example: assert arrays.distinct( [5, 5, 1, 5, 2, 1, 1, 9] ) == [1, 2, 5, 9]
151pub fn distinct[T](a []T) []T {
152 return uniq(a.sorted(a < b))
153}
154