Skip to content
Advertisement

More efficient way to sort unique values from array of arrays by occurrences in PHP

What would be the most efficient PHP way to get unique values from an array of arrays and sort them by number of occurrences from most frequent to least?

Example input array:

Array
(
    [0] => Array
        (
            [0] => A
            [1] => B
            [2] => C
            [3] => D
        )
    [1] => Array
        (
            [0] => A
            [1] => C
            [2] => D
        )
    [2] => Array
        (
            [0] => C
            [1] => F
            [2] => X
        )
)

Would result in this output array:

Array
(
    [0] => C    // 3
    [1] => A    // 2
    [2] => D    // 2
    [3] => B    // 1
    [4] => F    // 1
    [5] => X    // 1
)

The alphabetical order of values with same number of occurrences is not important.

So far I’m merging the array of arrays:

$all_posts = call_user_func_array( 'array_merge', $results );

Then creating a new array where values become keys. And values are the number of times they occur in the original array of arrays.

$posts_by_count = array();
foreach( $all_posts as $apost ) {
    $posts_by_count[ $apost ] = 0;
    foreach( $results as $tag_posts ) {
        if( in_array( $apost, $tag_posts ) ) {
            $posts_by_count[ $apost ]++;
        }
    }
}

Then I can sort by value

arsort($posts_by_count);

And create a new array where keys become values again.

$sorted_posts = array();
foreach($posts_by_count as $k => $v) {
    $sorted_posts[] = $k;
}

pprint( $sorted_posts );

What would be a more efficient way to do that?

Advertisement

Answer

The simplest I can come up with is to start with the array_merge(), but using the splat (...) to merge all of the arrays. Then use the inbuilt array_count_values() to summarize the values and then arsort() to sort them…

$all_posts = array_merge(...$results );
$posts_by_count = array_count_values($all_posts);
arsort($posts_by_count);

This gives the output of…

Array
(
    [C] => 3
    [A] => 2
    [D] => 2
    [B] => 1
    [F] => 1
    [X] => 1
)

using

print_r(array_keys($posts_by_count));

gives…

Array
(
    [0] => C
    [1] => A
    [2] => D
    [3] => B
    [4] => F
    [5] => X
)
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement