I have a poll which has 4 choices, sometimes people vote for the same things and choices end up in a tie. I'm looking for a way to break this tie.
The poll variables are always different the below is just an example of how they come. I'm currently doing this with messy if statements and randomizing results for each scenario or one === the other.
<?php
$choice1=4;
$choice2=4;
$choice3=2;
$choice4=4;
if ($choice1==$choice2) {
$a = ['$choice1','$choice2'];
$breaker = $a[mt_rand(0, count($a)-1)];
echo $breaker;
}elseif ($choice1==$choice3) {
$a = ['$choice1','$choice3'];
$breaker = $a[mt_rand(0, count($a)-1)];
echo $breaker;
}elseif ($choice1==$choice4) {
$a = ['$choice1','$choice4'];
$breaker = $a[mt_rand(0, count($a)-1)];
echo $breaker;
}elseif ($choice2==$choice1) {
$a = ['$choice2','$choice1'];
$breaker = $a[mt_rand(0, count($a)-1)];
echo $breaker;
//etc...
// This goes on and on also goes up to 3 way ties and 4 way ties.
This method seems extremely inelegant, also the number of votes is going to increase as more and more users register to vote so it is not scalable at this point any suggestions?
This approach uses an array with two set of sorts.
// As many choices as you would like
$choices = [
['id' => 1, 'name' => 'choice1', 'count' => 4],
['id' => 2, 'name' => 'choice2', 'count' => 4],
['id' => 3, 'name' => 'choice3', 'count' => 2],
['id' => 4, 'name' => 'choice4', 'count' => 4],
['id' => 5, 'name' => 'choice5', 'count' => 4],
['id' => 6, 'name' => 'choice6', 'count' => 4],
['id' => 7, 'name' => 'choice7', 'count' => 4],
['id' => 8, 'name' => 'choice8', 'count' => 6],
['id' => 9, 'name' => 'choice9', 'count' => 7],
['id' => 10, 'name' => 'choice10', 'count' => 4],
['id' => 11, 'name' => 'choice11', 'count' => 6],
['id' => 12, 'name' => 'choice12', 'count' => 6],
['id' => 13, 'name' => 'choice13', 'count' => 7],
['id' => 14, 'name' => 'choice14', 'count' => 3],
['id' => 15, 'name' => 'choice15', 'count' => 4],
];
// First, sort by count
usort($choices, function($a, $b) {
if ( $a['count'] < $b['count'] ) return -1; // a < b
elseif ( $a['count'] > $b['count'] ) return 1; // a > b
return 0;
});
// Now, all are sorted by count.
// Walk through and deal with items that have the same count.
$buf = []; // A temp buffer to keep all items with a certain count
$prevCcount = null;
$output = [];
foreach($choices as $choice) {
$count = $choice['count'];
echo sprintf('id %d count %d', $choice['id'], $choice['count']) . "
";
if ( $prevCount != $count ) {
// Possible new group of items with the same count
// Does the buffer have more than 1. If so, randomize.
if ( count($buf) > 1 ) {
echo "Shuffling " . count($buf) . "items
";
$shuffled = shuffle($buf);
if ( ! $shuffled ) {
throw new Exception('Failed to shuffle');
}
}
if ( count($buf) > 0 ) {
$output = array_merge($output, $buf);
$buf = [];
}
}
$prevCount = $count; // Keep track of count of previous item
$buf[] = $choice; // add current item to buffer
}
// Deal with the tail
// There will be 1 or more items still in the buffer that must be dealt with
echo "Final buf has " . count($buf) . " items
";
if ( count($buf) > 1 ) {
echo "Shuffling " . count($buf) . " items
";
$shuffled = shuffle($buf);
if ( ! $shuffled ) {
throw new Exception('Failed to shuffle');
}
}
$output = array_merge($output, $buf);
print_r($output);
echo "
";
You could use array_keys and max to get back which of them has the max score then chose one in that array in your liking
$choice1=4;
$choice2=4;
$choice3=2;
$choice4=4;
$arr = ["choice1" => $choice1,"choice2" => $choice2,"choice3" => $choice3,"choice4" => $choice4];
$winners = array_keys($arr, max($arr));
var_dump($winners);
Output:
array(3) {
[0]=>
string(7) "choice1"
[1]=>
string(7) "choice2"
[2]=>
string(7) "choice4"
}
You can then use your existing method to choose one of the three (in this case).
$breaker = $winners[mt_rand(0, count($winners)-1)];
echo $breaker;