1pub fn max_by<T, F>(collection: &[T], comparison: F) -> Option<T>
36where
37 T: Clone,
38 F: Fn(&T, &T) -> bool,
39{
40 if collection.is_empty() {
41 return None;
42 }
43
44 if collection.len() == 1 {
45 return Some(collection[0].clone());
46 }
47
48 let mut max = collection[0].clone();
49
50 for item in &collection[1..] {
51 if comparison(item, &max) {
52 max = item.clone();
53 }
54 }
55
56 Some(max)
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_max_by_age() {
65 #[derive(Debug, PartialEq, Eq, Clone)]
66 struct Person {
67 age: u32,
68 name: String,
69 }
70
71 let people = vec![
72 Person {
73 age: 25,
74 name: "Alice".to_string(),
75 },
76 Person {
77 age: 30,
78 name: "Bob".to_string(),
79 },
80 Person {
81 age: 20,
82 name: "Carol".to_string(),
83 },
84 ];
85
86 let result = max_by(&people, |a, b| a.age > b.age);
87 assert_eq!(
88 result,
89 Some(Person {
90 age: 30,
91 name: "Bob".to_string()
92 })
93 );
94 }
95
96 #[test]
97 fn test_max_by_name() {
98 #[derive(Debug, PartialEq, Eq, Clone)]
99 struct Person {
100 age: u32,
101 name: String,
102 }
103
104 let people = vec![
105 Person {
106 age: 25,
107 name: "Alice".to_string(),
108 },
109 Person {
110 age: 30,
111 name: "Bob".to_string(),
112 },
113 Person {
114 age: 20,
115 name: "Carol".to_string(),
116 },
117 ];
118
119 let result = max_by(&people, |a, b| a.name > b.name);
120 assert_eq!(
121 result,
122 Some(Person {
123 age: 20,
124 name: "Carol".to_string()
125 })
126 );
127 }
128
129 #[test]
130 fn test_max_by_empty_collection() {
131 #[derive(Debug, PartialEq, Eq, Clone)]
132 struct Person {
133 age: u32,
134 name: String,
135 }
136
137 let people: Vec<Person> = vec![];
138 let result = max_by(&people, |a, b| a.age > b.age);
139 assert_eq!(result, None);
140 }
141
142 #[test]
143 fn test_max_by_single_element() {
144 #[derive(Debug, PartialEq, Eq, Clone)]
145 struct Person {
146 age: u32,
147 name: String,
148 }
149
150 let person = Person {
151 age: 25,
152 name: "Alice".to_string(),
153 };
154 let people = vec![person.clone()];
155 let result = max_by(&people, |a, b| a.age > b.age);
156 assert_eq!(result, Some(person));
157 }
158
159 #[test]
160 fn test_max_by_with_struct_various_criteria() {
161 #[derive(Debug, PartialEq, Eq, Clone)]
162 struct Person {
163 age: u32,
164 name: String,
165 }
166
167 let people = vec![
168 Person {
169 age: 25,
170 name: "Alice".to_string(),
171 },
172 Person {
173 age: 30,
174 name: "Bob".to_string(),
175 },
176 Person {
177 age: 35,
178 name: "Carol".to_string(),
179 },
180 ];
181
182 let result_age = max_by(&people, |a, b| a.age > b.age);
184 assert_eq!(
185 result_age,
186 Some(Person {
187 age: 35,
188 name: "Carol".to_string()
189 })
190 );
191
192 let result_name = max_by(&people, |a, b| a.name > b.name);
194 assert_eq!(
195 result_name,
196 Some(Person {
197 age: 35,
198 name: "Carol".to_string()
199 })
200 );
201 }
202
203 #[test]
204 fn test_max_by_floats() {
205 let float_collection = vec![1.1, 2.2, 3.3, 4.4];
206 let result = max_by(&float_collection, |a, b| a > b);
207 assert_eq!(result, Some(4.4));
208
209 let more_floats = vec![5.5, 3.3, 5.5, 2.2];
210 let result_duplicate = max_by(&more_floats, |a, b| a > b);
211 assert_eq!(result_duplicate, Some(5.5));
212
213 let negative_floats = vec![-1.1, -2.2, -0.5, -3.3];
214 let result_negatives = max_by(&negative_floats, |a, b| a > b);
215 assert_eq!(result_negatives, Some(-0.5));
216
217 let all_nan = vec![std::f64::NAN, std::f64::NAN];
218 let result_all_nan = max_by(&all_nan, |a, b| a > b);
219 assert!(result_all_nan.unwrap().is_nan());
222 }
223}