diff --git a/src/bin/43_iterators_indepth.rs b/src/bin/43_iterators_indepth.rs index 1ecd3fe..8a29291 100644 --- a/src/bin/43_iterators_indepth.rs +++ b/src/bin/43_iterators_indepth.rs @@ -255,6 +255,72 @@ fn main() -> std::io::Result<()> { println!("Max = {max}, Min = {min}"); // max_by and min_by + // any, all: applies a closure to an iterator and returns true is any/all the element return true for the closure + + // building collections with the collect method + // When any type implements the FromIterator trait, a collection of that type can be derived from an iterator + // with the collect method + // + + #[allow(unused_doc_comments)] + /** + * + * trait FromIterator: Sized { + * fn from_iter>(iter: T) -> Self; + * } + */ + #[allow(clippy::useless_vec)] + let numbers = vec![1, 2, 3, 4, 5, 6]; + let names = vec!["Brian".to_string(), "Obot".to_string(), "David".to_string()]; + let _numbers_iter = numbers.iter(); + let names_iter = names.iter(); + + let _collection = names_iter.collect::>(); + println!("Names: {names:?}"); + + // Extend traits allow types to add Iterable items to itself + let mut cars = vec!["Benz", "Toyota", "Nissan"]; + cars.extend(&["Jeep", "Tesla", "Honda"]); + println!("Cars: {cars:?}"); + + // All standard collection implement the Extend trait and so they have the extend method, so does String + // Array and slices which have fixed length do not + + // partition method divivdes an iterator items among two collection, using a closure to decide where each item belongs + let things = ["doorknob", "mushroom", "noddle", "giraffe", "grapefruit"]; + let (living, nonliving): (Vec<&str>, Vec<&str>) = things + .iter() + .partition(|thing| thing.as_bytes()[0] & 1 != 0); + + println!("Living Things: {living:?}"); + println!("None Living Things: {nonliving:?}"); + + // like collect, partition makes any type of collection you specify in the type annotation + + struct F32Range { + start: f32, + end: f32, + } + + impl Iterator for F32Range { + type Item = f32; + + fn next(&mut self) -> Option { + if self.start >= self.end { + return None; + } + let result = Some(self.start); + self.start += 0.1; + result + } + } + + for i in (F32Range { + start: 1.0, + end: 10.0, + }) { + println!("I: {i}"); + } Ok(()) } diff --git a/src/bin/44_collections.rs b/src/bin/44_collections.rs new file mode 100644 index 0000000..7c55655 --- /dev/null +++ b/src/bin/44_collections.rs @@ -0,0 +1,88 @@ +fn main() { + // Common collection types in Rust + // Vec: Growable array + // VecDeque: Double Ended Queue + // LinkedList: Doubly Linked List + // BinaryHeap: Max Heap + // HashMap: key-value hash table + // BTreeMap: sorted key-value table + // HashSet: unoredered hash based set + // BTreeSet: sorted set + + // empty vector + #[allow(unused_mut, unused_variables)] + let mut numbers: Vec = vec![]; + + // vector with some content + #[allow(clippy::useless_vec)] + let words = vec!["Niche", "Opulence", "Insouciant"]; + let sub_word = words[0..2].to_vec(); + + println!("Sub word: {sub_word:?}"); + + fn first_word(s: &String) -> usize { + let bytes = s.as_bytes(); + println!("Bytes Form: {bytes:?}"); + + for (i, &item) in bytes.iter().enumerate() { + println!("Bytes [{i}]: {item}"); + } + + s.len() + } + + let first_name_end_index = first_word(&"Brian David Obot".to_string()); + println!( + "First Name = {}", + &"Brian David Obot"[0..first_name_end_index] + ); + + // methods available on slices + #[allow(clippy::useless_vec)] + let names = vec![1, 2, 3, 4, 5, 6]; + let _first = &names[..].first(); // returns a reference to the first item of a slice as an Option + let _last = &names[..].last(); // returns a reference to the last item of a slice as an Option + let _item = &names[..].get(10); // get the item at the index, if the item exist or None + + // each of the methods above have a mut variant that returns a mutable reference to the items + // .to_vec(): Makes copies of the slice creating a new vector from the item in it, this is only available if the elements are cloneable + // + // .len(): returns the length of the slice + // .is_empty(): returns True if the slice contains no element + // + // Vector specific methods + // .capacity(): returns the capacity of a vector + // .reserve(n): reserves enough space for n more items in the vectors capacity + // .reserve_exact(n): reserves exactly enough space for n item and no more + // .shrink_to_fit(): tries to free up extra space is capaccity > length + // .push(value): Add an element to the vector + // .pop(): removes nd return the last element from a vector as an Option + // .insert(index, value) + // .remove(index) + // .resize(new_size, new_value): increase the length of a vector to new_size and fills extra spaces with new_value as needed + // .resize_with(new_len, closure): same as above, but uses a closure to generate the new_values + // .truncate(new_len): cut a vector to a length dropping all elements outide this length + // .clear(): same as truncate(0) + // .extend(iterable): takes a value that implements IntoIterator and extends the vector with the values from it + // .split_off(index): like truncate, but the dropped values are returns as a vector to the caller similar to pop but for many values + // .append(vec2): Moves all elements from vec2 into the vector leving vec2 empty afterwards + // .drain(range) + // .retain(test): drops all elements that don't pass the test provided in the function, similar to calling filter and then collect on a iterator + // .dedup(): drops duplicate adjacent values so that only one is left + // .reverse(): reverse a slice in place + // Once a slice is sorted it can be efficiently searched + // .binary_search(&value) + // .binary_search_by(&value, cmp) + // + // + // These methods work on arrays of arrays + // .concat(): return a new vector by concatenating all the slices + // .join(&seperator): same as above, except that the seperator is inserted between slices + // + // to get the index of an item in a slice use the position method on the iterator + // slice.iter().postion(|x| *x == value) + + // Random elements + // .choose(&mut rng) + // .shuffle(&mut rng) +}