Last active
February 4, 2025 22:59
-
-
Save ruescasd/cea0f68857c810c4cc79a99919884fe7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Example of how to implement this without mutable state. | |
/// This is a more functional approach, but I would not implement it this way | |
/// in real code because 1) it is probably less efficient, and 2) requires | |
/// an extra dependency (itertools). | |
use itertools::Itertools; | |
fn tally_votes(election: &Election, votes: &[Vote]) -> ResultData { | |
let grouped = votes | |
.into_iter() | |
.filter(|v| v.contest_id == election.id) | |
.map(|v| (v.choice_id, v)) | |
.into_group_map(); | |
let vote_counts: HashMap<u32, u32> = grouped | |
.into_iter() | |
.map(|(choice_id, votes)| (choice_id, votes.len() as u32)) | |
.collect(); | |
let results: Vec<ChoiceResult> = election | |
.choices | |
.iter() | |
.map(|choice| ChoiceResult { | |
choice_id: choice.id, | |
total_count: *vote_counts.get(&choice.id).unwrap_or(&0), | |
}) | |
.sorted_by(|a, b| b.total_count.cmp(&a.total_count)) | |
.collect(); | |
let total_votes = results.iter().map(|r| r.total_count).sum(); | |
let winner = if results.len() > 1 && results[0].total_count == results[1].total_count { | |
None // Tie case: No winner | |
} else { | |
results.first().and_then(|r| { | |
if r.total_count > 0 { | |
election | |
.choices | |
.iter() | |
.find(|c| c.id == r.choice_id) | |
.cloned() | |
} else { | |
None | |
} | |
}) | |
}; | |
ResultData { | |
contest_id: election.id, | |
total_votes, | |
results, | |
winner, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment