【问题标题】:uasort bad performance sorting an array of object with custom orderuasort 性能不佳,对具有自定义顺序的对象数组进行排序
【发布时间】:2016-08-24 06:53:44
【问题描述】:

我必须对一个名为“内容”的对象数组进行排序,如下所示:

"articles" => array:106 [▼
  0 => array:5 [▼
    "id" => 467823568
    "title" => "my tittle"
    "data" => "my data"
    "category" => 23
    "order" => 2
  ]
  1 => array:5 [▼
    "id" => 46782356433
    "title" => "my tittle 2"
    "data" => "my data 2"
    "category" => 25
    "order" => 1
  ]
  ...
]

顺序定义在 2 个数组中,category_oorder_o 如下:

"category_o" => array:21 [▼
      0 => 25
      1 => 95
      2 => 135
      3 => 72
      4 => 4
      5 => 23
      6 => 7
      7 => 803
      ...
]

我希望文章按属性“类别”和category_o 数组中指定的自定义顺序排序,然后再按属性“顺序”和order_o 中指定的其他自定义顺序进行第二次排序。

我使用uasort方法对文章进行排序:

// Call sort function
uasort($articles,  array($this, "sortByCategoryOrder"));

使用我的自定义函数sortByCategoryOrder($left, $right);:

function sortByCategoryOrder($leftItem, $rightItem){
    // Array that contains order
    $order = $this->category_o; 
    // Exchange key with value, so we can access "position by value"
    $flipped = array_flip($order); 
    // Init default value for position
    $rightPos = 0;
    $leftPos = 0;

    // Check if order of current category is present:
    // the $category_o array could not have all order
    // values of articles
    if ( (array_key_exists($leftItem["category"], $flipped)) && (array_key_exists($rightItem["category"], $flipped)) ){
      // NO MISSING: the 2 element have order
      $leftPos = $flipped[$leftItem["category"]];
      $rightPos = $flipped[$rightItem["category"]];

    }else if (array_key_exists($leftItem["category"], $flipped)) {
        // MISS RIGHT: the right elmenet has not custom order specified! 
        $leftPos = $flipped[$leftItem["category"]];
        $rightPos = $leftPos+1;

    }else if (array_key_exists($rightItem["category"], $flipped)){
        // MISS LEFT: the left elmenet has not custom order specified! 
        $rightPos = $flipped[$rightItem["category"]];
        $leftPos = $rightPos+1;        

    }else{
        // MISS LEFT AND RIGHT: the 2 articles have no custom order specified!            
        $rightPos = 99999;
        $leftPos = 99999;
    }

    // Make the comparation
    return $leftPos >= $rightPos;   
}

我还有一个名为 sortByOrder($left, $right); 的函数,它按 order_o 数组值对文章进行排序。

排序大约需要 12 秒。 2000 篇文章。 uasort 真的很慢还是我在自定义订单功能中犯了一些错误? 谢谢


解决方案:

感谢@Ahmad Hajjar,我找到了正确的解决方案。

我编写了另一种方法,为每个内容设置新属性category_oorder_o,并使用双自然升序 和php 的方法array_multisort()。 性能提升和当前 2000 篇文章 传递 来自 ca。大约 9 秒1 秒

我报告我的新方法,希望它是有希望的:

public function sortArticles($articles, $type)
{
    // init sorted
    $sorted = array();

    // Array that contains order
    $order_c = $this->category_o; 
    // Exchange key with value, so we can access "position by value"
    $flipped_c = array_flip($order_c); 

    // Array that contains order
    $order_o = $this->order_o; 
    // Exchange key with value, so we can access "position by value"
    $flipped_o = array_flip($order_o); 

    // Iterate each article
    foreach ($articles as $article) {

        // If custom order was specified set it to article
        // Otherwise, set 99999 value.
        if ( array_key_exists( $article["category"], $flipped_c) ){
            $article["category_o"] = $flipped_c[$article["category"]];
        }else{
            $article["category_o"] =  99999;
        }

        // If custom order was specified set it to article
        // Otherwise, set 99999 value.
        if ( array_key_exists($article["order"], $flipped_o) ){
            $article["order_o"] =  $flipped_o[$article["order"]];
        }else{
            $article["order_o"] =  99999;
        }

        // Push new article inside array
        array_push($sorted, $article);
    }

    // get a list of sort columns and their data to pass to array_multisort
    $sort = array();
    foreach($sorted as $key => $value) {
        $sort['order_o'][$key] = $value['order_o'];
        $sort['category_o'][$key] = $value['category_o'];
    }

    // Determinate order type, category or order
    if (strcmp($type, "category") == 0) {
        // sort by category_o asc and then order_o asc
        array_multisort($sort['category_o'], SORT_ASC, $sort['order_o'], SORT_ASC,$sorted);
    }else{
        // sort by order_o asc and then category_o asc
        array_multisort($sort['order_o'], SORT_ASC, $sort['category_o'], SORT_ASC,$sorted); 
    }

    // Return sorted array
    return $sorted;
}

【问题讨论】:

  • 如果文章存储在数据库中,为什么不按您需要的任何字段从数据库中获取它们?

标签: php arrays performance sorting


【解决方案1】:

我认为这是模型设计问题。我会改变我的模型来存储 category_o 等级以及类别值和 order_o 等级以及它们的值,然后从数据库中获取它们,按你需要的顺序排序......所以当你从数据库中获取数组时,你会得到它像这样

"articles" => array:106 [▼
  0 => array:5 [▼
    "id" => 467823568
    "title" => "my tittle"
    "data" => "my data"
    "category" => 23
    "category_o" => 5
    "order" => 2
    "order_o" => 1
  ]
  1 => array:5 [▼
    "id" => 46782356433
    "title" => "my tittle 2"
    "data" => "my data 2"
    "category" => 25
    "category_o" => 0
    "order" => 1
    "order_o" => 2
  ]
  ...
]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    相关资源
    最近更新 更多