【问题标题】:logic to sort the multidimensional product array对多维产品数组进行排序的逻辑
【发布时间】:2021-01-05 08:17:43
【问题描述】:

我必须根据价格或大小对多维数组进行排序,但问题是,它有一个问题,它排序的第一个数组总是错误的,我尝试使用 usort 等,但它们都给出了相同的结果,我们有一个需要根据价格或尺寸分类的产品列表。我找到了很多答案,但问题仍然存在。产品应根据价格排序,即从低到高或尺寸将按宽度排序,例如产品尺寸 120 x 60,因此 120 是宽度,它应该是最后一个产品

对多维数组进行排序的函数

function array_sort($array, $on, $order=SORT_ASC){
   $new_array = array();
   $sortable_array = array();
   if (count($array) > 0) {
      foreach ($array as $k => $v) {
         if (is_array($v)) {
            foreach ($v as $k2 => $v2) {
                if ($k2 == $on) {
                    $sortable_array[$k] = $v2;
                }
            }
        } else {
            $sortable_array[$k] = $v;
        }
    }

    switch ($order) {
        case SORT_ASC:
            asort($sortable_array);
            break;
        case SORT_DESC:
            arsort($sortable_array);
            break;
    }

    foreach ($sortable_array as $k => $v) {
        $new_array[$k] = $array[$k];
    }
 }
 return $new_array; }

这是我要排序的数组

$sortingArray = Array(
    '0' => Array(
       'id' => 1287,
       'data-price' => '£209.95',
       'size' => '120 x 60'
    ),
    '1' => Array(
       'id' => 1263,
       'data-price'=> '£14.95',
       'size' => '18 x 13'
     ),

    '2' => Array(
       'id' => 1264,
       'data-price' => '£15.95',
       'size' => '20 x 15'
    ),

   '3' => Array(
      'id' => 1245,
      'data-price' => '£29.95',
      'size' => '30 x 20'
   ),

   '4' => Array
       (
        'id' => 1315,
        'data-price' => '£39.95',
        'size' => '50 x 13'
      ),
    '5' => Array(
        'id' => 1275,
        'data-price' => '£94.95',
        'size' => '60 x 40'
    ),
   '6' => Array
      (
        'id' => 1281,
        'data-price' => '£119.95',
        'size' => '75 x 50'
      ),

   );

输出结果

$rectangleProductDetails = array_sort($sortingArray, 'size', SORT_ASC);
print_r($rectangleProductDetails);

【问题讨论】:

  • 首先正确解释如何您希望这些项目按大小排序。这些看起来像宽度/高度值或其他东西 - 所以首先在这里执行这些公式中包含的“乘法”可能是最有意义的,这样产品就可以按表面积排序......?
  • @CBroe no product can't be sorted based on the surface area, 它应该是价格,或者如果我们选择尺寸,那么它应该是宽度,例如产品尺寸 120 x 60 所以 120 是宽度,它应该是最后一个产品

标签: php arrays sorting


【解决方案1】:

建议的解决方案:

function array_sort(array $array, string $on, string $order = 'ASC') {
    $sortableArray = $array;
    switch ($on) {
        case 'size':
            usort($sortableArray, 'sortBySize');
            break;
        case 'price':
            usort($sortableArray, 'sortByPrice');
            break;
        default:
            return $array;
            break;
    }

    if (strtoupper($order) === 'DESC') {
        return array_reverse($sortableArray);
    }

    return $sortableArray;
}

function sortByPrice(array $a, array $b) {
    return (float) mb_substr($a['data-price'], 1) <=> (float) mb_substr($b['data-price'], 1);
}

function sortBySize(array $a, array $b) {
    return (int) $a['size'] <=> (int) $b['size'];
}

它是如何工作的:

  • 它切换排序标准并选择正确的排序回调(从单独定义的函数中)与usort 一起使用。如果提供了不受支持的值,它将返回原始订单。
  • 数组始终按升序排序(即使提供了一些虚假值作为顺序)。如果定义了降序,我们使用array_reverse以相反的顺序返回排序后的数组。
  • 由于您已指定仅应使用宽度对大小进行排序,因此它通过将大小值转换为整数来进行排序(因为整数值仅考虑到第一个非数字字符的数字)。
  • 按价格排序需要提取金额,这是通过mb_substr($priceVariable, 1) 完成的(它消除了第一个字符)。请注意,substr 在这里不起作用,因为井号是一个多字节字符,所以必须使用 substring 函数的多字节版本。
  • 两种排序功能都使用spaceship operator

最后,请注意 $on 排序标准与数组键不完全匹配(我使用 'price' 而不是 'data-price';它们可以匹配 - 就像 'size' 一样 - 但不必这样做) .这样做的好处是,如果数组中的索引发生变化,您只需要修改排序回调,而不必在调用自定义 array_sort 函数的每个地方都进行修改。

【讨论】:

【解决方案2】:

您需要将 size 转换为 int

可能是这样的

usort($sortingArray, function($a, $b) {
    //you can calculate your size and sort the result
    //or split it into 2 number and then sort it
    return intval($a["size"]) < intval($b["size"]) ? -1 : 1;
});

【讨论】:

  • 不确定在这里简单地转换为 int 是否有意义。 120 x 60 转换为 int 会得到 120。所以你每次只考虑第一个维度,第二个维度对排序结果完全没有影响。现在 OP 并没有具体说明他们想要如何排序,但我的猜测是,大小为 10 x 1 的项目可能应该被认为小于大小为 5 x 500 的项目。
  • 不是简单的,而是需要,我试着告诉你如何去做
  • 编辑了我的答案,也许是这样的?还是谢谢
【解决方案3】:

阅读您要实现的目标,我认为以下是实现解决方案的正确方法。

由于您需要几种不同的方法来根据其字段的值对数组进行排序,并根据他们自己的需要,我认为一种策略类型的模式将适合这种情况。

为此,我定义了几个函数,一个是清理包含价格的字符串,然后使用太空船运算符进行比较。

对于尺寸,我们简单地获取宽度并比较intvals。

最后,默认值只会应用常规比较。

function priceSort($on)
{
    return function ($item, $other) use ($on) {
        $itemPrice = filter_var($item[$on], FILTER_SANITIZE_NUMBER_FLOAT);
        $otherPrice = filter_var($other[$on], FILTER_SANITIZE_NUMBER_FLOAT);

        return floatval($itemPrice) <=> floatval($otherPrice);
    };
}

function widthSort($on)
{
    return function ($item, $other) use ($on) {
        $itemWidth = explode('x', str_replace(' ', '', $item[$on]))[0];
        $otherWidth = explode('x', str_replace(' ', '', $other[$on]))[0];

        return intval($itemWidth) <=> intval($otherWidth);
    };
}

function defaultSort($on)
{
    return function ($item, $other) use ($on) {
        return $item[$on] <=> $other[$on];
    };
}

function determineSortStrategy($on)
{
    switch ($on) {
        case 'size':
            $strategy = widthSort($on);
            break;
        case 'data-price':
            $strategy = priceSort($on);
            break;
        default:
            $strategy = defaultSort($on);
            break;
    }

    return $strategy;
}

function orderBased($strategy, $order)
{
    if ($order === SORT_DESC) {
        $strategy = function ($item, $other) use ($strategy) {
            return -1 * $strategy($item, $other);
        };
    }

    return $strategy;
}

function array_sort($array, $on = 'id', $order = SORT_ASC)
{
    $strategy = determineSortStrategy($on);
    $strategy = orderBased($strategy, $order);

    usort($array, $strategy);

    return $array;
}

$result = array_sort($sortingArray, 'data-price', SORT_DESC);

echo '<pre>';
print_r($result);
echo '</pre>';

【讨论】:

    猜你喜欢
    • 2010-10-13
    • 1970-01-01
    • 2011-10-23
    • 2014-02-25
    • 2012-04-22
    • 2016-09-27
    相关资源
    最近更新 更多