// Code is in the preload fn person_builder(first_name: &str, last_name: &str) -> Person { Person { first_name: first_name.into(), last_name: last_name.into() } }
- // Code is in the preload
- fn person_builder(first_name: &str, last_name: &str) -> Person {
Person { first_name: String::from(first_name), last_name: String::from(last_name) }- Person { first_name: first_name.into(), last_name: last_name.into() }
- }
use std::iter::Iterator; use std::collections::{BTreeMap, btree_map}; // The use of InitF allows us to remove the Clone bound on V - you supply a closure that returns a start value fn reduce<K, V, InitF, F, I> (iter: I, init: InitF, f: F) -> btree_map::IntoIter<K, V> where // Reference because we don't want it to modify the previous value, only look at it. F: Fn(V, &V) -> V, InitF: Fn() -> V, K: Ord, I: Iterator<Item=(K, V)>, { let mut out_map = BTreeMap::new(); for (k, v) in iter { // Entry API lets us avoid repeating ourselves let slot = out_map.entry(k).or_insert_with(&init); *slot = f(v, slot); } out_map.into_iter() }
- use std::iter::Iterator;
- use std::collections::{BTreeMap, btree_map};
// we can use "impl I" when codewars adds rust 1.26// instead of boxing the iterators and returning an btree_map::IntoIterfn reduce<TK, TV, F, I> (v : Box<I>, s : TV, f : F) -> btree_map::IntoIter<TK, TV>- // The use of InitF allows us to remove the Clone bound on V - you supply a closure that returns a start value
- fn reduce<K, V, InitF, F, I> (iter: I, init: InitF, f: F) -> btree_map::IntoIter<K, V>
- where
F : Fn(TV, TV) -> TV,TK : Eq + Ord,TV : Clone,I : Iterator<Item=(TK, TV)>,- // Reference because we don't want it to modify the previous value, only look at it.
- F: Fn(V, &V) -> V,
- InitF: Fn() -> V,
- K: Ord,
- I: Iterator<Item=(K, V)>,
- {
let mut m: BTreeMap<TK, TV> = BTreeMap::new();for (k, x) in *v {if let Some(p) = m.remove(&k) {m.insert(k, f(x, p));} else {m.insert(k, f(x, s.clone()));}- let mut out_map = BTreeMap::new();
- for (k, v) in iter {
- // Entry API lets us avoid repeating ourselves
- let slot = out_map.entry(k).or_insert_with(&init);
- *slot = f(v, slot);
- }
m.into_iter()- out_map.into_iter()
- }
use std::collections::HashSet; #[test] fn returns_summarised_word_count() { let unreduced = Box::new(vec![("a", 2), ("b", 1), ("a", 1), ("x", 5), ("b", 9)].into_iter()); let reduced = reduce(unreduced, || 0, |s, v| s + *v); // items in "reduced" are in no particular order, compare using set comparison let reduced_set: HashSet<(&str, i32)> = reduced.collect(); let expected: HashSet<(&str, i32)> = vec![("a", 3), ("b", 10), ("x", 5)].into_iter().collect(); assert_eq!(reduced_set, expected); }
- use std::collections::HashSet;
- #[test]
fn returns_summariesed_word_count() {- fn returns_summarised_word_count() {
- let unreduced = Box::new(vec![("a", 2), ("b", 1), ("a", 1), ("x", 5), ("b", 9)].into_iter());
let reduced = reduce(unreduced, 0, |s, v| s + v);- let reduced = reduce(unreduced, || 0, |s, v| s + *v);
- // items in "reduced" are in no particular order, compare using set comparison
- let reduced_set: HashSet<(&str, i32)> = reduced.collect();
- let expected: HashSet<(&str, i32)> = vec![("a", 3), ("b", 10), ("x", 5)].into_iter().collect();
- assert_eq!(reduced_set, expected);
- }