1 /***********************************************************************************************
2 *	Copyright: © 2017-2021 UI Manufaktur UG
3 *	License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
4 *	Authors: UI Manufaktur Team
5 *	Documentation [DE]: https://ui-manufaktur.com/docu/uim-core/containers/arry
6 ************************************************************************************************/
7 module uim.core.containers.array_;
8 
9 @safe:
10 import uim.core;
11 
12 /// Counts appearance of equal items
13 auto countsEquals(T)(in T[] baseArray...) {
14 	return countsEquals(baseArray, null);
15 }
16 unittest {
17 	assert(countsEquals(1) == [1:1uL]);
18 	assert(countsEquals(1, 1) == [1:2uL]);
19 	assert(countsEquals(1, 2) == [1:1U, 2:1UL]);
20 }
21 
22 /// Counts the occourence of values in an array
23 auto countsEquals(T)(in T[] baseArray, in T[] validValues = null) {
24 	size_t[T] results;
25 	auto checkValues = (validValues ? baseArray.filters(validValues) : baseArray); 
26 	foreach(v; checkValues) {
27 		if (v in results) results[v]++;
28 		else results[v] = 1;
29 	}
30 	return results;
31 }
32 unittest {
33 	assert(countsEquals([1]) == [1:1uL]);
34 	assert(countsEquals([1, 1]) == [1:2uL]);
35 	assert(countsEquals([1, 2]) == [1:1uL, 2:1uL]);
36 	assert(countsEquals([1, 2], [1]) == [1:1uL]);
37 }
38 
39 auto firstPosition(T)(in T[] baseArray, in T value) {
40 	foreach(index, item; baseArray) if (item == value) return index;
41 	return -1;
42 	 }
43 unittest {
44 }
45 
46 /// Creates a associative array with all positions of a value in an array
47 auto positions(T)(in T[] baseArray...) {
48 	size_t[][T] results = positions(baseArray, null);
49 	return results; }
50 unittest {
51 	assert(positions(1) == [1:[0UL]]);
52 	assert(positions(1, 1) == [1:[0UL, 1UL]]);
53 	assert(positions(1, 2) == [1:[0UL], 2:[1UL]]);
54 }
55 
56 /// Creates a associative array with all positions of a value in an array
57 size_t[][T] positions(T)(in T[] baseArray, in T[] validValues = null) {
58 	size_t[][T] results;
59 	auto checkValues = (validValues ? baseArray.filters(validValues) : baseArray); 
60 	foreach(pos, v; checkValues) {
61 		if (v in results) results[v] ~= pos;
62 		else results[v] = [pos];
63 	}
64 	return results;
65 }
66 unittest {
67 	assert(positions([1]) == [1:[0UL]]);
68 	assert(positions([1, 1]) == [1:[0UL, 1UL]]);
69 	assert(positions([1, 2]) == [1:[0UL], 2:[1UL]]);
70 	assert(positions([1, 2], [1]) == [1:[0UL]]);
71 }
72 
73 /// adding items into array
74 @safe T[] add(T)(in T[] baseArray, in T[] newItems...) {
75 	return add(baseArray, newItems);
76 }
77 unittest {
78 	assert([1,2,3].add(4) == [1,2,3,4]);
79 	assert([1,2,3].add(4,5) == [1,2,3,4,5]);
80 	assert([1.0,2.0,3.0].add(4.0,5.0) == [1.0,2.0,3.0,4.0,5.0]);
81 	assert(["1","2","3"].add("4","5") == ["1","2","3","4","5"]);
82 }
83 
84 /// adding items into array
85 @safe T[] add(T)(in T[] baseArray, in T[] newItems) {
86 	T[] results = baseArray.dup;
87 	results ~= newItems;
88 	return results;
89 }
90 unittest {
91 	assert([1,2,3].add([4,5]) == [1,2,3,4,5]);
92 	assert([1.0,2.0,3.0].add([4.0,5.0]) == [1.0,2.0,3.0,4.0,5.0]);
93 	assert(["1","2","3"].add(["4","5"]) == ["1","2","3","4","5"]);
94 }
95 
96 /// change positions
97 @safe void change(T)(ref T left, ref T right) {
98 	T buffer = left;
99 	left = right;
100 	right = buffer;
101 } 
102 /// Changing positions of elements in array
103 @safe T[] change(T)(T[] values, size_t firstPosition, size_t secondPosition) {
104 	if ((firstPosition >= values.length) || (secondPosition >= values.length) || (firstPosition == secondPosition)) return values;
105 
106 	T[] results = values.dup;
107 	T buffer = results[firstPosition];
108 	results[firstPosition] = results[secondPosition];
109 	results[secondPosition] = buffer;
110 	return results;
111 } 
112 unittest{
113 	assert(change([1, 2, 3, 4], 1, 2) == [1, 3, 2, 4]);
114 	assert(change(["a", "b", "c", "d"], 3, 2) == ["a", "b", "d", "c"]);
115 	assert(change(["a", "b", "c", "d"], 1, 1) == ["a", "b", "c", "d"]);
116 	assert(change(["a", "b", "c", "d"], 1, 9) == ["a", "b", "c", "d"]);
117 }
118 
119 // sub
120 @safe T[] sub(T)(T[] lhs, T rhs, bool multiple = false) {
121 	auto result = lhs.dup;
122 	if (multiple) { while(rhs.isIn(result)) result = result.sub(rhs); }
123 	else foreach(i, value; result) { 
124 		if (value == rhs) {
125 			result = result.remove(i);
126 			break;
127 		}
128 	}
129 	return result;
130 } 
131 unittest {
132 	assert([1, 2, 3].sub(2) == [1, 3]); 
133 	assert([1, 2, 3, 2].sub(2, true) == [1, 3]); 
134 }
135 
136 // sub(T)(T[] lhs, T[] rhs, bool multiple = false)
137 @safe T[] sub(T)(T[] lhs, T[] rhs, bool multiple = false) {
138 	auto result = lhs.dup;
139 	foreach(v; rhs) lhs = lhs.sub(v, multiple);
140 	return lhs;
141 } 
142 unittest {
143 	assert([1, 2, 3].sub([2]) == [1, 3]); 
144 	assert([1, 2, 3, 2].sub([2], true) == [1, 3]); 
145 	assert([1, 2, 3, 2].sub([2, 3], true) == [1]); 
146 	assert([1, 2, 3, 2, 3].sub([2, 3], true) == [1]); 
147 }
148 
149 // filters(T)(T[] lhs, T[] rhs, bool multiple = false)
150 @safe T[] filters(T)(T[] baseArray, T[] filterValues...) {
151 	return filters(baseArray, filterValues);
152 }
153 unittest {
154 	assert([1, 2, 3].filters(2) == [2]); 
155 	assert([1, 2, 3].filters() == []); 
156 	assert([1, 2, 3].filters(1, 2) == [1, 2]); 
157 }
158 
159 @safe T[] filters(T)(T[] baseArray, T[] filterValues) {
160 	T[] results;
161 	foreach(v; baseArray) if (filterValues.has(v)) results ~= v;
162 	return results;
163 } 
164 unittest {
165 	assert([1, 2, 3].filters([2]) == [2]); 
166 	assert([1, 2, 3].filters([]) == []); 
167 }
168 
169 @safe OUT[] castTo(OUT, IN)(IN[] values) {
170 	OUT[] results; results.length = values.length;
171 	foreach(i, value; value) result[i] = to!OUT(value);
172 	return results;
173 }
174 
175 unittest {
176 	auto values = [1, 2, 3, 4]; 
177 	change(values[2], values[3]); 
178 	assert(values == [1, 2, 4, 3]);
179 
180 	assert([1,2,3,4].change(1, 3) == [1, 4, 3, 2]);
181 }
182 
183 bool exist(T)(in T[] values, in T[] checkValues...) {
184 	return has(values, checkValues);
185 }
186 bool has(T)(in T[] values, in T[] checkValues...) {
187 	return has(values, checkValues);
188 }
189 unittest {
190 	assert([1,2,3,4].has(1));
191 	assert(![1,2,3,4].has(5));
192 	assert([1,2,3,4].has(1, 2));
193 	assert(![1,2,3,4].has(5, 1));
194 }
195 
196 bool has(T)(in T[] values, in T[] checkValues) {
197 	bool result = false;
198 	foreach (cv; checkValues) {		
199 		result = false;
200 		foreach (value; values) if (value == cv) result = true;		
201 		if (!result) return false; 
202 	}
203 	return result;
204 }
205 unittest {
206 	assert([1,2,3,4].has([1]));
207 	assert(![1,2,3,4].has([5]));
208 	assert([1,2,3,4].has([1, 2]));
209 	assert(![1,2,3,4].has([5, 1]));
210 }
211 
212 size_t index(T)(T[] values, T value) {
213 	foreach (count, key; values) if (key == value) return count;		
214 	return -1;
215 }
216 unittest {
217 	assert([1,2,3,4].index(1) == 0);
218 	assert([1,2,3,4].index(0) == -1);
219 }
220 
221 size_t[] indexes(T)(T[] values, T value) {
222 	size_t[] results;
223 	foreach (count, key; values) if (key == value) results ~= count;		
224 	return results;
225 }
226 unittest {
227 	assert([1,2,3,4].indexes(1) == [0]);
228 	assert([1,2,3,4].indexes(0) == null);
229 	assert([1,2,3,4,1].indexes(1) == [0,4]);
230 }
231 
232 size_t[][T] indexes(T)(T[] values, T[] keys) {
233 	size_t[][T] results;
234 	foreach (key; keys) results[key] = indexes(values, key);		
235 	return results;
236 }
237 unittest {
238 	assert([1,2,3,4].indexes([1]) == [1:[0UL]]);
239 	assert([1,2,3,4,1].indexes([1]) == [1:[0UL, 4UL]]);
240 }