按相同对象数量对PHP数组进行排序

3
有没有办法按照这种方式排序数组?例如,如果我有这个数组:
$array = array("foo", "bar", "item", "item", "foo", "foo");

我想把它排序成这样:“foo”,“foo”,“foo”,“item”,“item”,“bar”,有办法做到吗?


1
我可以看到它们被分组了。是什么决定了foo < item < bar? - Reece45
这是相同项目的数量,例如,有3个“foo”,2个“item”和1个“bar”,因此顺序从相同项目的数量最多到最少。 - williamg
所有的项目都是字符串吗?那会简化事情。 - John Carter
6个回答

4

这个可以吗?

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

将为您提供

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

或者你必须将它们作为重复值使用吗?如果是,你可以选择以下内容:
usort($array,create_function('$a,$b',
    'return $GLOBALS["array1"][$a]<$GLOBALS["array1"][$b];'));

这是丑陋的代码,但展示了技术。使用php 5.3闭包也可以很容易地使其看起来好看,但我不知道您是否使用的是5.3版本。如果是,则会像这样:

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

好主意使用array_count_values,我正想建议这个。 - John Carter
不客气。为了记录,我已经添加了闭包的完整示例。 - Michael Krelin - hacker

2

首先,您需要计算每个值的出现次数(array_count_values),然后使用usort按照您的标准对元素进行排序:

<?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);

1

usort() 可以工作。array_count_values() 非常方便。根据您需要进行的计算,这可能会更清晰和高效。如果有很多重复值(100+),您可能还想考虑使用 array_fill() 而不是 for 循环:

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
}

0

让我们试试这个:

// 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;
    }
}

可以使用一些 PHP 函数进行缩短,但您已经明白该如何处理了。


0
您可以使用以下函数按值在数组中出现的频率进行排序:
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');
}

并按以下方式使用:

$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);

这将产生

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

这是一个相当不寻常的排序过程,最简单的方法是分为两到三个步骤进行。

首先计算不同对象的数量,然后对对象计数进行排序,并从中生成已排序的对象数组。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接