Skip to content

Instantly share code, notes, and snippets.

@ruescasd
Last active February 4, 2025 22:59
Show Gist options
  • Save ruescasd/cea0f68857c810c4cc79a99919884fe7 to your computer and use it in GitHub Desktop.
Save ruescasd/cea0f68857c810c4cc79a99919884fe7 to your computer and use it in GitHub Desktop.
/// 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