如何按数组定义的特定顺序对大量项目进行排序?

时间:2011-06-29 08:36:38

标签: php algorithm sorting

我需要实现一些特定的排序算法。我有两个数组:

$items = array(
  array("id" => "…", "type" => "alpha"),
  array("id" => "…", "type" => "beta"),
  array("id" => "…", "type" => "company"),
  array("id" => "…", "type" => "marketing"),
  array("id" => "…", "type" => "beta"),
  array("id" => "…", "type" => "company"),
  array("id" => "…", "type" => "alpha"),
  array("id" => "…", "type" => "alpha"),
  array("id" => "…", "type" => "company"),
  array("id" => "…", "type" => "marketing"),
  […]
);

$order = array("company", "marketing", "alpha", "beta" );

正如您可能想象的那样,我需要根据$items中指定的顺序对$order进行排序。

5 个答案:

答案 0 :(得分:4)

运行$items并使用“type”作为键将所有内容索引到字典中。然后运行$order并查找与该“类型”对应的项目列表,并将它们附加到排序列表中。在O(n+k)中运行,k为|order|

答案 1 :(得分:3)

您可以使用usort

对自定义比较功能进行排序
usort($items, "cmp");

function cmp($a, $b)
{
  $order = array("company" => 0, "marketing" => 1, "alpha" => 2, "beta" => 3);

  $order_a = $order[$a["type"]];
  $order_b = $order[$b["type"]];

  if ($order_a == $order_b) {
    return 0;
  }
  return ($order_a < $order_b) ? -1 : 1;
}

答案 2 :(得分:2)

与Ozgur非常相似!!但是,我将构建功能来处理订单中未考虑的意外值。它们放在排序数组的末尾。

usort($items,"compare");
echo "<pre>";
print_r($items);
echo "</pre>";

function compare($a, $b) {
  $order = array("company" => 1, "marketing" => 2, "alpha" => 3, "beta" => 4);
  $ax = $order[$a['type']]; $bx = $order[$b['type']];    
  if ($ax < 1) return 1;
  if ($ax == $bx) return 0;
  return ($ax > $bx) ? 1 : -1;
}

答案 3 :(得分:1)

使用usort,这是一种高效的PHP算法,可以根据您提供的条件运行。

http://php.net/manual/en/function.usort.php

这是一个正在运行的代码,您可以根据您的数据对其进行基准测试: http://codepad.org/MRpZQkKk

如果你想改变排序标准,这会给你更多的控制权, 也很复杂,它很快,应该是O(n log n)(内部快速排序), 空间复杂度也很低。

以下是更多信息: Which sort algorithms does PHP's usort apply?

  <?php

    $items = array(
      array("id" => "…", "type" => "alpha"),
      array("id" => "…", "type" => "beta"),
      array("id" => "…", "type" => "company"),
      array("id" => "…", "type" => "marketing"),
      array("id" => "…", "type" => "beta"),
      array("id" => "…", "type" => "company"),
      array("id" => "…", "type" => "alpha"),
      array("id" => "…", "type" => "alpha"),
      array("id" => "…", "type" => "company"),
      array("id" => "…", "type" => "marketing"),

    );

    $order = array("company", "marketing", "alpha", "beta" );

    $orderIndexes = array(); /* cache indexes of the order keys */
    for($i = 0 ; $i < count($order) ; $i++ )
    {
       $orderIndexes[$order[$i]] = $i ;
    }


    /* we have something like :
    $orderIndexes = array('company' => 0 , 'marketing' => 1 , ....);
    */



    function myCriteria($item1,$item2)   /* this is the function used to decide order */
    {  global $orderIndexes;
       $index1 = $orderIndexes[$item1['type']];
       $index2 = $orderIndexes[$item2['type']];

       return $index1 - $index2 ;    // negative means $item1 precedes $item2

    }

usort($items,"myCriteria");
print_r($items);

?>

答案 4 :(得分:1)

您可以实现用户排序功能的简单实现:

function mySort($a, $b) {
    global $order;

    return array_search($a['type'], $order) - array_search($b['type'], $order);
}

然后执行usort()

usort($items, 'mySort');

可能效率不高,但works


<强>更新
为了避免多次调用array_search(),您可以事先翻转$order数组。这将通过简单的查找替换array_search()

$reversed_order = array_flip($order);

function mySort($a, $b) {
    global $reversed_order;

    return $reversed_order[$a['type']] - $reversed_order[$b['type']];
}

应该更有效率。 (demo