h_math/functionality.rs
1use std::collections::{HashMap, HashSet};
2use std::hash::Hash;
3use std::iter::zip;
4
5
6#[derive(Debug)]
7pub enum ListToHashMapError<K> {
8 LengthMismatch { keys_len: usize, values_len: usize },
9 DuplicateKeys { duplicates: Vec<K> },
10}
11
12
13/// This trait converts the values of a HashMap into a HashSet. The values must implement the Eq, Hash,
14/// and Clone traits to be stored in a HashSet. The function will return a HashSet containing all the unique values
15/// from the HashMap. For example, if the HashMap contains the pairs (1, "a"), (2, "b"), and (3, "a"),
16/// the resulting HashSet will contain "a" and "b", because "a" is duplicated in the values of the HashMap.
17/// Example usage:
18/// let mut map = HashMap::new();
19/// map.insert(1, "a");
20/// map.insert(2, "b");
21/// map.insert(3, "a");
22/// let value_set = map.h_hashmap_values_to_hashset();
23/// The result will be a HashSet containing "a" and "b", because those are the unique values in the HashMap.
24pub trait HashMapValuesToHashSet<V>
25where
26 V: Eq + Hash + Clone,
27{
28 fn h_hashmap_values_to_hashset(&self) -> HashSet<V>;
29}
30
31impl<K, V> HashMapValuesToHashSet<V> for HashMap<K, V>
32where
33 V: Eq + Hash + Clone,
34{
35 fn h_hashmap_values_to_hashset(&self) -> HashSet<V> {
36 let mut set: HashSet<V> = HashSet::new();
37 for (_key, value) in self.iter() {
38 set.insert(value.clone());
39 }
40 set
41 }
42}
43
44
45/// This trait converts the keys of a HashMap into a HashSet. The keys must implement the Eq, Hash,
46/// and Clone traits to be stored in a HashSet. The function will return a HashSet
47/// containing all the unique keys from the HashMap. For example, if the HashMap contains the pairs (1, "a"), (2, "b"),
48/// and (3, "a"),
49/// the resulting HashSet will contain 1, 2, and 3, because those are the unique keys in the HashMap.
50/// Example usage:
51/// let mut map = HashMap::new();
52/// map.insert(1, "a");
53/// map.insert(2, "b");
54/// map.insert(3, "a");
55/// let key_set = map.h_hashmap_keys_to_hashset();
56/// The result will be a HashSet containing 1, 2, and 3, because those are the unique keys in the HashMap.
57pub trait HashMapKeysToHashSet<K>
58where
59 K: Eq + Hash + Clone,
60{
61 fn h_hashmap_keys_to_hashset(&self) -> HashSet<K>;
62}
63
64impl<K, V> HashMapKeysToHashSet<K> for HashMap<K, V>
65where
66 K: Eq + Hash + Clone,
67{
68 fn h_hashmap_keys_to_hashset(&self) -> HashSet<K> {
69 let mut set: HashSet<K> = HashSet::new();
70 for (key, _value) in self.iter() {
71 set.insert(key.clone());
72 }
73 set
74 }
75}
76
77
78/// This function converts a list of keys and a list of values into a HashMap.
79/// The keys and values must implement the Eq, Hash, and Clone traits to be stored in a HashMap.
80/// The function will return a Result containing a HashMap where each key from the list of keys is associated with the corresponding value
81/// from the list of values, or a vector of errors if issues are found (length mismatch or duplicate keys).
82/// For example, if the list of keys is [1, 2, 3] and the list of values is ["a", "b", "c"],
83/// the resulting HashMap will contain the pairs (1, "a"), (2, "b"), and (3, "c").
84/// If lengths don't match or there are duplicate keys, it returns errors.
85/// Example usage:
86/// let keys = vec![1, 2, 3];
87/// let values = vec!["a", "b", "c"];
88/// let map = h_list_to_hashmap(&keys, &values);
89/// The result will be Ok(HashMap) containing the pairs (1, "a"), (2, "b"), and (3, "c").
90
91pub fn h_list_to_hashmap<K, V>(keys: &[K], values: &[V]) -> Result<HashMap<K, V>, Vec<ListToHashMapError<K>>>
92where
93 K: Eq + Hash + Clone,
94 V: Clone,
95{
96 if keys.len() != values.len() {
97 return Err(vec![ListToHashMapError::LengthMismatch {
98 keys_len: keys.len(),
99 values_len: values.len(),
100 }]);
101 }
102
103 let mut map = HashMap::new();
104 let mut duplicates = Vec::new();
105
106 for (key, value) in keys.iter().zip(values.iter()) {
107 if map.contains_key(key) {
108 duplicates.push(key.clone());
109 } else {
110 map.insert(key.clone(), value.clone());
111 }
112 }
113
114 if !duplicates.is_empty() {
115 return Err(vec![ListToHashMapError::DuplicateKeys {
116 duplicates,
117 }]);
118 }
119
120 Ok(map)
121}
122
123
124
125
126
127/// this trait converts a list of values into a HashSet.
128/// The values must implement the Eq, Hash, and Clone traits to be stored in a HashSet.
129/// The function will return a tuple of (HashSet containing all the unique values from the list, number of duplicates removed).
130/// For example, if the list contains ["a", "b", "a", "c"],
131/// the result will be (HashSet containing "a", "b", "c", 1), because "a" was duplicated.
132/// Example usage:
133/// let values = vec!["a", "b", "a", "c"];
134/// let (value_set, dupes) = values.h_list_to_hashset();
135/// value_set will contain "a", "b", "c", and dupes will be 1.
136
137pub trait ListToHashSet {
138 type Item;
139
140 fn h_list_to_hashset(&self) -> (HashSet<Self::Item>, usize)
141 where
142 Self::Item: Eq + Hash + Clone;
143}
144
145impl<T> ListToHashSet for [T]
146where
147 T: Eq + Hash + Clone,
148{
149 type Item = T;
150
151 fn h_list_to_hashset(&self) -> (HashSet<Self::Item>, usize) {
152 let mut set = HashSet::new();
153 let mut duplicates = 0;
154 for item in self.iter() {
155 if !set.insert(item.clone()) {
156 duplicates += 1;
157 }
158 }
159 (set, duplicates)
160 }
161}
162
163use std::time::Duration;
164
165#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
166pub struct HBlockPreformance {
167 label: Option<&'static str>,
168 duration: Duration,
169 file: &'static str,
170 line: u32,
171}
172
173impl HBlockPreformance {
174 pub fn new() -> Self {
175 HBlockPreformance { label: None, duration: Duration::new(0, 0), line: 0, file: "" }
176 }
177 pub fn set_new(label: Option<&'static str>, duration: Duration, line: u32, file: &'static str) -> Self {
178 HBlockPreformance { label: label, duration: duration, line: line, file: file}
179 }
180 pub fn print(&self) {
181 println!("label: {:?}, duration: {:?}, line: {}, file: {}", self.label, self.duration, self.line, self.file);
182 }
183 pub fn print_fields_specified(&self, fields: &[HBlockPreformanceField]) {
184 let mut count: usize = 1;
185 if fields.contains(&HBlockPreformanceField::Label) {
186 if fields.len() == count {
187 print!("label: {:?}\n", self.label);
188 }
189 else {
190 print!("label: {:?}, ", self.label);
191 }
192 count += 1;
193 }
194 if fields.contains(&HBlockPreformanceField::Duration) {
195 if fields.len() == count {
196 print!("duration: {:?}\n", self.duration);
197 }
198 else {
199 print!("duration: {:?}, ", self.duration);
200 }
201 count += 1;
202 }
203 if fields.contains(&HBlockPreformanceField::File) {
204 if fields.len() == count {
205 print!("file: {:?}\n", self.file);
206 }
207 else {
208 print!("file: {:?}, ", self.file);
209 }
210 }
211 if fields.contains(&HBlockPreformanceField::Line) {
212 print!("line: {:?}\n", self.line);
213 }
214 }
215 pub fn print_label(&self) {
216 println!("label: {:?}", self.label);
217 }
218 pub fn print_duration(&self) {
219 println!("duration: {:?}", self.duration);
220 }
221 pub fn print_file(&self) {
222 println!("label: {}", self.file);
223 }
224 pub fn print_line(&self) {
225 println!("line: {}", self.line);
226 }
227}
228
229
230#[macro_export]
231macro_rules! h_block_preformance {
232 ($code:block) => {
233 {
234 let start = std::time::Instant::now();
235 $code
236 HBlockPreformance::set_new(None, start.elapsed(), line!(), file!())
237 }
238 };
239}
240
241
242#[derive(Debug, PartialEq, Eq)]
243pub enum HBlockPreformanceLogPrintOrder {
244 Normal,
245
246 LabelAlphabeticAscending,
247
248 DurationAscending,
249
250 FileAlphabeticalAscending,
251
252 LineAscending,
253}
254
255
256#[derive(Debug, PartialEq, Eq)]
257pub enum HBlockPreformanceField {
258 Label,
259 Duration,
260 File,
261 Line,
262}
263
264
265/*
266#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
267pub struct HBlockPreformanceLog {
268 log: Vec<HBlockPreformance>,
269 labels: Vec<Option<&'static str>>,
270 files: Vec<&'static str>,
271 lines: Vec<u32>,
272}
273
274impl HBlockPreformanceLog {
275 pub fn new() -> Self {
276 HBlockPreformanceLog { log: Vec::new(), labels: Vec::new(), files: Vec::new(), lines: Vec::new() }
277 }
278 pub fn push(&mut self, new: HBlockPreformance) {
279 if cfg!(debug_assertions) {
280 self.labels.push(new.label);
281 self.files.push(new.file);
282 self.lines.push(new.line);
283 self.log.push(new);
284 }
285 }
286 fn find_new_indecies(&self, field: HBlockPreformanceField, old_vec: &Vec<&HBlockPreformance>, new_vec: &Vec<&HBlockPreformance>) -> Vec<usize> { // returns &[(old index, new index)]
287 let mut indecies: Vec<usize> = Vec::new();
288 for i in old_vec {
289 let mut new_index: usize = 0;
290
291 for j in new_vec {
292 if field == HBlockPreformanceField::Label {
293 if i.label == j.label {
294 new_index += 1;
295 break;
296 }
297 }
298 if field == HBlockPreformanceField::Duration {
299 if i.duration == j.duration {
300 new_index += 1;
301 break;
302 }
303 }
304 if field == HBlockPreformanceField::File {
305 if i.file == j.file {
306 new_index += 1;
307 break;
308 }
309 }
310 if field == HBlockPreformanceField::Line {
311 if i.line == j.line {
312 new_index += 1;
313 break;
314 }
315 }
316 }
317 indecies.push(new_index);
318 }
319 indecies
320 }
321 fn ordered_list<'a>(&self, new_indecies: Vec<usize>, normal_ref_list: &Vec<&'a HBlockPreformance>) -> Vec<&'a HBlockPreformance> {
322 let mut ordered: Vec<&'a HBlockPreformance> = Vec::new();
323 for index in new_indecies {
324 ordered.push(normal_ref_list[index]);
325 }
326 ordered
327 }
328
329
330 pub fn print(&self, order: HBlockPreformanceLogPrintOrder, fields_included: &[HBlockPreformanceField]) {
331 if cfg!(debug_assertions) {
332 let mut ordered_blocks: Vec<&HBlockPreformance> = Vec::new();
333 let logged_blocks: Vec<&HBlockPreformance> = self.log.iter().collect();
334
335
336 if order == HBlockPreformanceLogPrintOrder::LabelAlphabeticAscending {
337 let mut labels_normal: Vec<&Option<&'static str>> = self.labels.iter().collect();
338 labels_normal.sort();
339 let mut logged_blocks_label_sorted: Vec<&HBlockPreformance> = self.log.iter().collect();
340 for (a, b) in zip(logged_blocks_label_sorted, labels_normal) {
341 a.label = *b;
342 }
343 let new_indecies: Vec<usize> = self.find_new_indecies(HBlockPreformanceField::Label, &logged_blocks, &logged_blocks_label_sorted);
344
345 ordered_blocks = self.ordered_list(new_indecies, &logged_blocks);
346 }
347
348 for i in ordered_blocks {
349 i.print_fields_specified(fields_included);
350 }
351 }
352 }
353
354}
355
356
357#[macro_export]
358macro_rules! h_block_preformance_log {
359 ($logger_struct:expr, $code:block) => {
360 {
361 if cfg!(debug_assertions) {
362 let start = std::time::Instant::now();
363 $code
364 $logger_struct.push(HBlockPreformance::set_new(None, start.elapsed(), line!(), file!()))
365 }
366 }
367 };
368}
369
370*/
371#[cfg(test)]
372mod tests {
373 use super::*;
374 use std::collections::HashMap;
375
376 #[test]
377 fn test_hashmap_values_to_hashset() {
378 let mut map = HashMap::new();
379 map.insert(1, "a");
380 map.insert(2, "b");
381 map.insert(3, "a");
382 let set = map.h_hashmap_values_to_hashset();
383 assert_eq!(set.len(), 2);
384 assert!(set.contains("a"));
385 assert!(set.contains("b"));
386 }
387
388 #[test]
389 fn test_hashmap_keys_to_hashset() {
390 let mut map = HashMap::new();
391 map.insert(1, "a");
392 map.insert(2, "b");
393 map.insert(3, "a");
394 let set = map.h_hashmap_keys_to_hashset();
395 assert_eq!(set.len(), 3);
396 assert!(set.contains(&1));
397 assert!(set.contains(&2));
398 assert!(set.contains(&3));
399 }
400
401 #[test]
402 fn test_h_list_to_hashmap() {
403 let keys = vec![1, 2, 3];
404 let values = vec!["a", "b", "c"];
405 let map = h_list_to_hashmap(&keys, &values).unwrap();
406 assert_eq!(map.get(&1), Some(&"a"));
407 assert_eq!(map.get(&2), Some(&"b"));
408 assert_eq!(map.get(&3), Some(&"c"));
409 }
410
411 #[test]
412 fn test_h_list_to_hashmap_length_mismatch() {
413 let keys = vec![1, 2];
414 let values = vec!["a", "b", "c"];
415 let result = h_list_to_hashmap(&keys, &values);
416 assert!(result.is_err());
417 }
418
419 #[test]
420 fn test_h_list_to_hashmap_duplicate_keys() {
421 let keys = vec![1, 1, 2];
422 let values = vec!["a", "b", "c"];
423 let result = h_list_to_hashmap(&keys, &values);
424 assert!(result.is_err());
425 }
426
427 #[test]
428 fn test_list_to_hashset() {
429 let list = vec!["a", "b", "a", "c"];
430 let (set, dupes) = list.h_list_to_hashset();
431 assert_eq!(set.len(), 3);
432 assert!(set.contains("a"));
433 assert!(set.contains("b"));
434 assert!(set.contains("c"));
435 assert_eq!(dupes, 1);
436 }
437}
438
439
440