Skip to content

Instantly share code, notes, and snippets.

@eiriklv
Created March 3, 2017 13:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eiriklv/30ed442ef3f0705cf84bce485bfafd79 to your computer and use it in GitHub Desktop.
Save eiriklv/30ed442ef3f0705cf84bce485bfafd79 to your computer and use it in GitHub Desktop.
Modeling an election in JavaScript
/**
* Dependencies
*/
const sortBy = require('sort-by');
/**
* Representing an election as a data structure
*/
const votes = [
{ id: 0, voterId: 'a', zone: 'Oslo', party: 'Miljøpartiet De Grønne' },
{ id: 1, voterId: 'b', zone: 'Oslo', party: 'Fremskrittspartiet' },
{ id: 2, voterId: 'c', zone: 'Oslo', party: 'Arbeiderpartiet' },
{ id: 3, voterId: 'd', zone: 'Oslo', party: 'Piratpartiet' },
{ id: 4, voterId: 'e', zone: 'Oslo', party: 'Liberalistene' },
{ id: 5, voterId: 'f', zone: 'Oslo', party: 'Høyre' },
{ id: 6, voterId: 'g', zone: 'Oslo', party: 'Sosialistisk Venstreparti' },
{ id: 7, voterId: 'h', zone: 'Oslo', party: 'Venstre' },
{ id: 8, voterId: 'i', zone: 'Oslo', party: 'Piratpartiet' },
{ id: 9, voterId: 'j', zone: 'Oslo', party: 'Høyre' },
{ id: 10, voterId: 'k', zone: 'Oslo', party: 'Høyre' },
{ id: 11, voterId: 'l', zone: 'Trondheim', party: 'Miljøpartiet De Grønne' },
{ id: 12, voterId: 'm', zone: 'Trondheim', party: 'Fremskrittspartiet' },
{ id: 13, voterId: 'n', zone: 'Trondheim', party: 'Arbeiderpartiet' },
{ id: 14, voterId: 'o', zone: 'Trondheim', party: 'Piratpartiet' },
{ id: 14, voterId: 'o', zone: 'Trondheim', party: 'Piratpartiet' },
{ id: 15, voterId: 'p', zone: 'Trondheim', party: 'Piratpartiet' },
{ id: 16, voterId: 'q', zone: 'Bergen', party: 'Liberalistene' },
{ id: 17, voterId: 'r', zone: 'Bergen', party: 'Høyre' },
{ id: 18, voterId: 's', zone: 'Bergen', party: 'Sosialistisk Venstreparti' },
{ id: 19, voterId: 't', zone: 'Bergen', party: 'Sosialistisk Venstreparti' },
{ id: 20, voterId: 'u', zone: 'Bergen', party: 'Venstre' },
{ id: 21, voterId: 'v', zone: 'Bergen', party: 'Piratpartiet' },
{ id: 22, voterId: 'x', zone: 'Stavanger', party: 'Piratpartiet' },
{ id: 23, voterId: 'y', zone: 'Stavanger', party: 'Piratpartiet' },
{ id: 24, voterId: 'z', zone: 'Stavanger', party: 'Piratpartiet' },
{ id: 25, voterId: 'æ', zone: 'Stavanger', party: 'Piratpartiet' },
{ id: 26, voterId: 'ø', zone: 'Stavanger', party: 'Piratpartiet' },
{ id: 27, voterId: 'å', zone: 'Stavanger', party: 'Piratpartiet' },
];
/**
* Selection of fields (mapping)
*/
const voteIds = votes.map((vote) => vote.id);
const voterIds = votes.map((vote) => vote.voterId);
const zones = votes.map((vote) => vote.zone);
const parties = votes.map((vote) => vote.party);
/**
* Counting the amount of votes
*/
const amountOfVotes = votes.length;
/**
* Getting the sum for a specific party
*/
const amountOfVotesForPiratpartiet = votes
.filter((vote) => vote.party === 'Piratpartiet')
.length;
/**
* Function that takes a list and an element
* and returns a new list of unique elements
*/
function uniqueReducer(uniqueList, element) {
return uniqueList.includes(element) ?
uniqueList :
[...uniqueList, element];
}
/**
* Getting all the unique parties that are represented
*/
const partiesRepresented = votes
.map((vote) => vote.party)
.reduce(uniqueReducer, []);
/**
* Getting all the unique zones that are represented
*/
const zonesRepresented = votes
.map((vote) => vote.zone)
.reduce(uniqueReducer, []);
/**
* Group all the votes by party
*/
const votesGroupedByParty = votes
.reduce((votesByParty, vote) => {
return Object.assign({}, votesByParty, {
[vote.party]: [
...(votesByParty[vote.party] || []),
vote,
],
});
}, {});
/**
* Group all the votes by zone
*/
const votesGroupedByZone = votes
.reduce((votesByZone, vote) => {
return Object.assign({}, votesByZone, {
[vote.zone]: [
...(votesByZone[vote.zone] || []),
vote,
],
});
}, {});
/**
* Find the national winner party by counting all the votes per party
*/
const nationalWinner = partiesRepresented
.map((party) => ({ party, sum: votesGroupedByParty[party].length }))
.sort(sortBy('-sum'))
.map((result) => result.party)[0]
/**
* Find a summary of each zone
*/
const summaryByZone = zonesRepresented
.map((zone) => {
return {
zone: zone,
sums: partiesRepresented
.map((party) => ({
party,
sum: votesGroupedByZone[zone]
.filter((vote) => vote.party === party)
.length
}))
};
});
/**
* Find the winner for each zone
*/
const winnerByZone = summaryByZone
.map((summary) => ({
zone: summary.zone,
winner: summary.sums
.sort(sortBy('-sum'))
.map((result) => result.party)[0]
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment