开发者

Ordering PHP array by number of identical objects

Is there anyway to order an array in this way? For example if I had this array:

$array = array("foo", "bar", "item", "item", "foo", "foo");

And I wanted to order it so that it was "foo", "foo", "foo", "item", "item", 开发者_Python百科"bar" is there any way to do that?


Would this do?

$array1 = array_count_values($array);
arsort($array1);
var_dump($array1);

will give you

array(3) {
  ["foo"]=>
  int(3)
  ["item"]=>
  int(2)
  ["bar"]=>
  int(1)
}

or do you necessarily need them as repeated values? if yes, you may go for something like:

usort($array,create_function('$a,$b',
    'return $GLOBALS["array1"][$a]<$GLOBALS["array1"][$b];'));

This is ugly code, but demonstrates the technique. It is also easy to make it good-looking with php 5.3 closures, but I don't know if you're on 5.3. That would look like this:

$acount=array_count_values($array = array("foo", "bar", "item", "item", "foo", "foo"));
usort($array,function($a,$b) use ($acount) { return $acount[$a]<$acount[$b]; });


First you have to count occurrence of each value (array_count_values), then use usort to sort element by your criteria:

<?php

$array = array('foo', 'bar', 'bar', 'foo', 'bar', 'foo', 'foobar', 'foo', 'foo', 'foobar', 'bar', 'foo');

$tmp = array_count_values($array);
usort($array, function($e1, $e2) use($tmp) {
    return $tmp[$e2] - $tmp[$e1];
});

var_dump($array);


usort() could work. array_count_values() comes in handy though. With the calculations you need to make, this might be a little more clear and efficient . If there are a lot of repeated values (100+), you may also want to consider using array_fill() instead of the for loop:

function getSortedGroupArray($array) {
  $return = array();
  $values = array_count_values($array);
  sort($values);
  foreach($values as $count => $value) {
    for($i = 0; $i < $count; ++$i) {
      $return[] = $value;
    }
  }
  return $return
}


That's quite and unusual sort process, it would be simplest to do as a two or three step process.

First count the different objects, then sort the object counts and generate from that the sorted object array.


Lets try this:

// First, lets count the number of objects  
$sort_by_term = array();
foreach($array as $string)
{
   if(isset($sort_by_term[$string]))
   {
       $sort_by_term[$string] += 1;
   }
   else
   {
       $sort_by_term[$string] = 1;
   }
}

// Next let's sort them by number
$sort_by_count = array();
foreach($sort_by_term as $term => $count)
{
    $sort_by_count[$count][] = $term;
}

// Now lets combine them
$final_array = array();
foreach($sort_by_count as $count => $term)
{
    while($count > 0)
    {
        $final_array[] = $term;
        $count -= 1;
    }
}

Could be shortened using some of PHP's functions, but you get the idea of what has to be done.


You can use the following function for ordering by the frequency with which a value appears in an array:

function array_count_sort(&$array, $direction = 1)
{
    // Could do with a better way of making $counts and $dir available to the
    // sorting function, but this will do for illustrative purposes.
    global $counts, $dir; 
    $counts = array_count_values($array);
    $dir = $direction;

    if (!function_exists('array_count_sort_cmp')) {
        function array_count_sort_cmp($a, $b) {
            global $counts, $dir;

            $c = $counts[$a];
            $d = $counts[$b];

            if ($c == $d) return 0;
            return ($c < $d) ? -$dir : $dir;
        }
    }

    usort($array, 'array_count_sort_cmp');
}

And use it in the following way:

$test = array("foo", "bar", "item", "item", "foo", "foo");
print_r($test);
array_count_sort($test);
print_r($test);
array_count_sort($test, -1);
print_r($test);

which would yield

Array
(
    [0] => foo
    [1] => bar
    [2] => item
    [3] => item
    [4] => foo
    [5] => foo
)
Array
(
    [0] => bar
    [1] => item
    [2] => item
    [3] => foo
    [4] => foo
    [5] => foo
)
Array
(
    [0] => foo
    [1] => foo
    [2] => foo
    [3] => item
    [4] => item
    [5] => bar
)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜