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 )