0

I have an array:

Array
(
    [0] => Alex
    [1] => Michael
    [2] => Harry
    [3] => Dave
    [4] => Michael
    [5] => Victor
    [6] => Harry
    [7] => Alex
    [8] => Mary
    [9] => Mary
)

I want to write to a function that will return an array with elements that most number of time repeated. For example, the output array should have Alex, Micheal, Hary, and Mary because each one of them is repeated twice. IF Alex was repeated three times, then the output array should only have Alex.

function writeIn($ballot) {

    $count = array_count_values($ballot);

    arsort($count);

    foreach($count as $c => $name) {
        $arr[] = $name;
    }
}
2
  • How do you build the array? You could just use the name as the index then you can only have 1 for each. Commented Dec 14, 2019 at 1:17
  • Or if the question is only about +2 php.net/manual/en/function.array-unique.php#81513 Commented Dec 14, 2019 at 1:32

3 Answers 3

1

Three problems with your current function.

  1. $name and $c are reversed in the foreach loop. The names will be the keys
  2. The loop doesn't stop after it gets the top counts
  3. The function doesn't return anything.

You can fix it like this:

After you count and sort with

$count = array_count_values($ballot);
arsort($count);

you can get the max value by taking the first value from the rsorted counts.

$max = reset($count);

Then as you iterate, when you reach a name with a count !== the max count, break out of the loop.

foreach($count as $name => $c) {
    if ($c !== $max) break;
    $arr[] = $name;
}

And don't forget to return the result.

return $arr;

Another possibility is to use some built-in PHP functions. I agree starting with array_count_values() seems like a good idea.

$count = array_count_values($ballot);

After that you can get the max count using max()

$max = max($count);

Filter the counts to return only items with the max count

$top = array_filter($count, function($n) use ($max) {
     return $n == $max;
});

// PHP 7.4 version
// $top = array_filter($count, fn($n) => $n == $max);

And return the keys from that array to get the names.

return array_keys($top);
Sign up to request clarification or add additional context in comments.

Comments

0

This solution keeps track as it goes.

function writeIn($ballot) {
    $tally = []; // How many votes did each person get
    $choice = []; // List of names with max occurrences
    $max = 0;
    array_walk($ballot, function($item) use(&$choice, &$tally, &$max) {
        if ( ! array_key_exists($item, $tally) ) {
            // If we haven't seen this name, add it with a count of 1
            $tally[$item] = 1;
        } else {
            // We saw this name already so increment its count
            $tally[$item]++;
        }
        // Check to see if the current name has exceeded or reached max
        if ( $tally[$item] > $max ) {
            // This is a new max so replace the choice list with this name
            $choice = [$item];
            $max = $tally[$item];
        } elseif ( $tally[$item] == $max ) {
            // This name has reached the current max so add it to the list
            $choice[] = $item;
        }
    });
    // Now we have the list of names with the most occurrences.
    return $choice;
}

Comments

0

Don't Panic's answer is a good one. There is also an optional search parameter to array_keys() to pass a search parameter which is applicable to this problem. Once you have the results sorted by count, and you know the max count, you can use that parameter to only return keys(name)s that match the associated count value.

<?php

$ballot = ['Alex', 'Michael', 'Harry', 'Dave', 'Michael', 'Victor', 'Harry', 'Alex', 'Mary', 'Mary'];

function writeIn($ballot) {
    $count = array_count_values($ballot);

    arsort($count);
    $max = reset($count);

    return array_keys($count, $max);
}

var_dump( writeIn($ballot));

Returns:

array(4) {
  [0]=>
  string(4) "Alex"
  [1]=>
  string(7) "Michael"
  [2]=>
  string(5) "Harry"
  [3]=>
  string(4) "Mary"
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.