You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// getfnrun(){// Type annotations are just added to show slice &[i32].// So `get` supports range as input. Returns slicelet v = vec![1,2,3];let x:Option<&i32> = v.get(1);// Single elementlet y:Option<&[i32]> = v.get(0..2);// Slice rangeletmut x = [1,2,3];// get_mut returns mutable reference for val which can be modified for value inside VectorifletSome(elem) = x.get_mut(1){*elem = 9;}println!("x is {:?}", x);// [1, 9, 3]}// user get with slice and let elsefnrun(){// The conversion of String to Vec at the start can be a key performance optimizationlet needle_chars:Vec<char> = needle.chars().collect();let needle_length = needle_chars.len();let haystack_chars:Vec<char> = haystack.chars().collect();for(idx_h, char_h)in haystack.chars().enumerate(){letSome(slice_h) = haystack_chars.get(idx_h..idx_h + needle_length)else{break;};if slice_h == needle_chars {return idx_h asi32;}}
-1}
Iteration: for item in numbers, numbers.iter(), numbers.enumerate()
fnrun(){let numbers = vec![1,2,3,4,5];// Direct iteration (takes ownership)for number in numbers {println!("{}", number);}// same asfor number in numbers.into_iter(){println!("{}", number);}// Iterator (borrows)for number in numbers.iter(){println!("{}", number);}// With indexfor(index, number)in numbers.enumerate(){println!("Index: {}, Number: {}", index, number);}}
Slicing: &vec[start..end]
fnrun(){// Example with Vec<char>let chars:Vec<char> = vec!['h','e','l','l','o'];let slice1 = &chars[1..4];// gets 'ell'println!("Char slice: {:?}", slice1);// Example with Vec<i32>let numbers:Vec<i32> = vec![1,2,3,4,5,6,7,8,9,10];let slice2 = &numbers[2..5];// gets [3, 4, 5]println!("Number slice: {:?}", slice2);// Using inclusive rangelet slice3 = &numbers[2..=5];// gets [3, 4, 5, 6]println!("Inclusive slice: {:?}", slice3);}
Splitting: split_at(), split_at_mut()
fnrun(){let numbers = vec![1,2,3,4,5,6];// Immutable splitlet(first, second) = numbers.split_at(3);println!("First half: {:?}", first);// [1, 2, 3]println!("Second half: {:?}", second);// [4, 5, 6]letmut numbers = vec![1,2,3,4,5,6];// Mutable splitlet(first, second) = numbers.split_at_mut(3);
first[0] = 10;
second[0] = 20;}fnrun(){letmut numbers = vec![1,2,3,4,5,6];// Split the vector at index 3let(first_half, second_half) = numbers.split_at_mut(3);// Now we can modify both halves independently
first_half[0] = 10;// Modifies [1, 2, 3]
second_half[0] = 20;// Modifies [4, 5, 6]println!("First half: {:?}", first_half);// [10, 2, 3]println!("Second half: {:?}", second_half);// [20, 5, 6]println!("Full vector: {:?}", numbers);// [10, 2, 3, 20, 5, 6]}fnrun(){let original_vec = vec![1,2,3,4,5,6,7,8,9,10];letmut new_vec = Vec::new();for(index,&element)in original_vec.iter().enumerate(){if index != 2{// Skip the 3rd element (index 2)
new_vec.push(element);}}println!("Original vector: {:?}", original_vec);println!("New vector (skipping 3rd position): {:?}", new_vec);}fnrun(){letmut original_vec = vec![1,2,3,4,5,6,7,8,9,10];// Use split_at_mut to get mutable sliceslet(first_part, second_part) = original_vec.split_at_mut(2);// Create a new vectorletmut new_vec = Vec::new();// Extend with the first two elements
new_vec.extend_from_slice(first_part);// Skip the third element and extend with the rest
new_vec.extend_from_slice(&second_part[1..]);println!("Original vector: {:?}", original_vec);println!("New vector (skipping 3rd position): {:?}", new_vec);}
Conversion: collect() to create from iterators
fnrun(){// String to Vec<char>let given = word.to_string();letmut chars:Vec<char> = given.chars().collect();// also works with &strlet text:&str = "hello world";let chars:Vec<char> = text.chars().collect();// HashMap<String, i32> to Vec<(String, i32)>letmut hash_map:HashMap<String,i32> = HashMap::new();
hash_map.insert("apple".to_string(),5);
hash_map.insert("banana".to_string(),2);
hash_map.insert("cherry".to_string(),8);let vec:Vec<(String,i32)> = hash_map.into_iter().collect();// HashMap<String, Vec<String>> to // values of HashMap Vec<Vec<String>> // and to // keys of HashMap Vec<String> letmut lookup:HashMap<String,Vec<String>> = HashMap::new();
lookup.insert("fruits".to_string(),vec!["apple".to_string(),"banana".to_string()]);
lookup.insert("vegetables".to_string(),vec!["carrot".to_string(),"potato".to_string()]);// same as let vec: Vec<Vec<String>> = lookup.into_iter().map(|(_, v)| v).collect();let values:Vec<Vec<String>> = lookup.values().cloned().collect();let vec:Vec<String> = lookup.keys().cloned().collect();}
2D operations: vec![vec![0; cols]; rows] for matrix creation
fnrun(){#[derive(Debug)]structStudent{name:String,grade:u8,}letmut students = vec![Student{ name:"Alice".to_string(), grade:85},Student{ name:"Bob".to_string(), grade:85},Student{ name:"Charlie".to_string(), grade:82},];// Sorts the slice with a key extraction function, preserving the initial order of equal elements.// The key in sort_by_key() refers to the value we want to sort by - it's a transformation function that extracts a comparable value from each element.// It's more like a "sorting key" or "comparison key" rather than a dictionary/hash key.
students.sort_by_key(|s| s.grade);
students.sort_by_key(|s| s.name.clone());println!("students are {:?}", students);}
compare vector to slice directly:
fnrun(){// You can compare a slice with a Vec directly in Rust since Vec implements Deref to slice. Here's how:let vec = vec![1,2,3];let slice = &[1,2,3];let are_equal = vec == slice;// true// Also works with string typeslet string_vec = vec!["hello","world"];let string_slice = &["hello","world"];let are_equal = string_vec == string_slice;// true}
Adding elements: push() for single characters: final_word.push('a')
Adding multiple elements: push_str() for string slices: final_word.push_str("hello") Note: String has an append()
method that takes ownership of another String and appends it to the current String.
It's similar to push_str() but
consumes the argument String instead of borrowing it.
Removing elements: remove last character: pop()
Slicing: get and &str[start..end]
fnrun(){let owned = String::from("world");let y:Option<&str> = owned.get(1..3);// str slicelet text = "hello";let z:Option<&str> = text.get(1..3);// y and z are Option<&str>// Type annotations are just added to show slice &str.// So `get` supports range as input. Returns slice. }
fnrun(){// Vec<chars> to Stringlet chars:Vec<char> = vec!['a','b','c','d','e'];// Rust provides the FromIterator trait implementation for String that can work with both references (iter()) and owned values (into_iter()). // When using iter(), the characters are implicitly copied since char is a Copy type, making it just as valid as using into_iter().// let s: String = chars.into_iter().collect();// this also works:// let s1: String = chars.collect();let s:String = chars.iter().collect();}
Splitting: split() to parse string into substrings
Use trim() to remove whitespace in strings.
Use to_lowercase() or to_uppercase() to ensure that you’re comparing strings in the same case
Use the regex crate for more complex string manipulation
fnrun(){// whitespace-separated wordslet sentence = "Rust is a great language for systems programming".to_string();let words:Vec<String> = sentence.split_whitespace().map(String::from).collect();println!("Words: {:?}", words);// First and last elementslet first_word = words.first().cloned().unwrap_or_default();let last_word = words.last().cloned().unwrap_or_default();println!("First word: {}, Last word: {}", first_word, last_word);// comma-separated values CSVlet csv = "apple,banana,cherry,date,elderberry".to_string();let fruits:Vec<String> = csv.split(',').map(String::from).collect();println!("Fruits: {:?}", fruits);// with vector First, last, and third elements// the clone here is for Option<&String> to String// could use unwrap and then clonelet first_fruit = fruits.first().cloned().unwrap_or_default();let last_fruit = fruits.last().cloned().unwrap_or_default();let third_fruit = fruits.get(2).cloned().unwrap_or_default();println!("First fruit: {}, Last fruit: {}, Third fruit: {}", first_fruit, last_fruit, third_fruit);// with CSV splittingletmut splits = csv.split(',');let first = splits.next().unwrap_or("").to_string();let last = splits.next_back().unwrap_or("").to_string();let third_alt = csv.split(',').nth(2).unwrap_or("").to_string();println!("First (alt): {}, Last (alt): {}, Third (alt): {}", first, last, third_alt);}
Replacement: replace() to manipulate string by replacing substrings
fnrun(){use std::collections::HashMap;letmut lookup:HashMap<String,usize> = HashMap::new();
lookup.insert("key".to_string(),9);println!("lookup is {:?}", lookup);// {"key": 9}// or_insert returns mutable reference for val which can be directly modified inside HashMaplet val = lookup.entry("key".to_string()).or_insert(0);*val = 1000;println!("lookup is {:?}", lookup);// {"key": 1000}// with add_modify
lookup.entry("key".to_string()).and_modify(|v| *v += 1);
lookup.entry("key".to_string()).and_modify(|v| *v += 1).or_insert(0);println!("Lookup contents: {:?}", lookup);// Lookup contents: {"key": 1002}}
Insertion: insert(key, value)
fnrun(){// Both approaches achieve the same result of decrementing the count for the key t_ch. The insert method will simply override the existing value with the new decremented count. While the entry API provides a more fluent interface for these operations, using insert directly is perfectly valid for updating existing values in a HashMap.// hash_s.entry(t_ch).and_modify(|count| *count -= 1);
hash_s.insert(t_ch, count - 1);}
fnrun(){// Both code snippets are functionally equivalent. They both handle the case of incrementing an existing count or initializing it to 1 if the key doesn't exist. The entry API version does it in one fluid chain, while the get/insert approach breaks it into two distinct steps. Both are valid ways to achieve the same result in a HashMap.// hash_s// .entry(s_ch)// .and_modify(|count| *count += 1)// .or_insert(1);let current_count = hash_s.get(&s_ch).unwrap_or(&0);
hash_s.insert(s_ch, current_count + 1);// get_mut returns mutable reference for val which can be modified for value inside HashifletSome(count) = hash_s.get_mut(&s_ch){*count += 1;}else{
hash_s.insert(s_ch,1);}}
Iteration: for (key, value) in lookup.iter()
Length: len()
Check if empty: is_empty()
Sorting: Convert to Vec<(&K, &V)> and use sort_by_key() or sort_by()
fnrun(){use std::collections::HashMap;letmut lookup:HashMap<String,i32> = HashMap::new();
lookup.insert("apple".to_string(),5);
lookup.insert("banana".to_string(),2);
lookup.insert("cherry".to_string(),8);// lookup.entry("key".to_string()).and_modify(|v| *v += 1).or_insert(0);
lookup
.entry("apple".to_string()).and_modify(|x| *x += 100).or_insert(0);letmut vec:Vec<(&String,&i32)> = lookup.iter().collect();// Unsorted values: [("cherry", 8), ("banana", 2), ("apple", 105)]println!("Unsorted vector: {:?}", vec);
vec.sort_by_key(|&(_k, v)| v);// Sorted vector by values: [("banana", 2), ("cherry", 8), ("apple", 105)]println!("Sorted vector by values: {:?}", vec);// same with sort_by
vec.sort_by(|a, b| a.1.cmp(b.1));
vec.sort_by_key(|&(k, _v)| k);// Sorted vector by keys: [("apple", 105), ("banana", 2), ("cherry", 8)]println!("Sorted vector by keys: {:?}", vec);// same with sort_by
vec.sort_by(|a, b| a.0.cmp(b.0));println!("Sorted vector by keys: {:?}", vec);}
one line iterators are useful (besides collect already included above)
fnrun(){// type annotations in some cases are just to briefly show type being returnedlet vec = vec![1,2,3];// count() gives us the length of the resulting iterator after applying operations like filter(), map(), or // other transformations. It's particularly useful when you want to count elements that meet // certain conditions or when working with iterator adaptors.// The pattern is especially common when dealing with generic iterators where you don't have //direct access to a len() method.let count:usize = vec.iter().filter(|&&x| x % 2 == 0).count();;let sum:i32 = vec.iter().sum();let has_even:bool = vec.iter().any(|x| x % 2 == 0);let find_two:Option<&i32> = vec.iter().find(|&&x| x == 2);let first:Option<&i32> = vec.iter().next();let max:Option<&i32> = vec.iter().max();let min:Option<&i32> = vec.iter().min();let last:Option<&i32> = vec.iter().last();let skip_first:Vec<&i32> = vec.iter().skip(1).collect();// Skips first element}
fnrun(){// Forward iteration (3 is excluded)for i in0..3{println!("{}", i);// prints 0, 1, 2}// Inclusive rangefor i in0..=3{println!("{}", i);// prints 0, 1, 2, 3}// Reversed iteration (3 is excluded)for i in(0..3).rev(){println!("Reversed: {}", i);}// Prints:// Reversed: 2// Reversed: 1// Reversed: 0// Safe index + 1 operationsfor idx in0..nums.len() - 1{let current = nums[idx];let next = nums[idx + 1];// always valid}// Range patterns in match expressionsmatch n {0..=3 => println!("small number"),4..=7 => println!("medium number"),
_ => println!("large number"),}// Step by using step_by()for i in(0..10).step_by(2){println!("{}", i);// prints 0, 2, 4, 6, 8}// Range with charsfor c in'a'..='z'{println!("{}", c);// prints a through z}// Range bounds checkinglet nums = vec![1,2,3,4,5];let slice = &nums[1..3];// safe slice from index 1 to 3 (exclusive) so gets [2, 3]}
Contains: range.contains(&value) to check if a range contains a value
fnrun(){let range = 1..=5;let value = 3;let is_in_range = range.contains(&value);println!("Is {} in range? {}", value, is_in_range);// prints true}