在子数组中按多个值对PHP数组进行排序

时间:2021-09-13 21:14:18

So I'm not exactly sure if the title fits it best, but here's what the array looks like:

所以我不确定标题是否最合适,但这是数组的样子:

array (
   [0] => array (
              [category] => 'Value_1'
              [date]     => '01/01/2011'
              [data]     => 'A'
          )
   [1] => array (
              [category] => 'Value_3'
              [date]     => '01/01/2000'
              [data]     => 'B'
          )
   [2] => array (
              [category] => 'Value_2'
              [date]     => '01/01/2011'
              [data]     => 'D'
          )
   [3] => array (
              [category] => 'Value_2'
              [date]     => '01/01/2010'
              [data]     => 'A'
          )
   [4] => array (
              [category] => 'Value_2'
              [date]     => '01/01/2011'
              [data]     => 'C'
          )
)

How I'd like this data to be sorted would be the following:

我希望如何对这些数据进行排序如下:

  1. Preserve the order of the categories
  2. 保留类别的顺序
  3. Within the categories, order by date DESC
  4. 在类别中,按日期DESC排序
  5. If dates appear multiple times, order by data alphabetically ASC
  6. 如果日期多次出现,请按字母顺序按ASC排序

The example array would then be sorted to array ([0], [1], [4], [2], [3]), more specifically:

然后将示例数组排序为数组([0],[1],[4],[2],[3]),更具体地说:

array (
   [0] => array (
              [category] => 'Value_1'
              [date]     => '01/01/2011'
              [data]     => 'A'
          )
   [1] => array (
              [category] => 'Value_3'
              [date]     => '01/01/2000'
              [data]     => 'B'
          )
   [2] => array (
              [category] => 'Value_2'
              [date]     => '01/01/2011'
              [data]     => 'C'
          )
   [3] => array (
              [category] => 'Value_2'
              [date]     => '01/01/2011'
              [data]     => 'D'
          )
   [4] => array (
              [category] => 'Value_2'
              [date]     => '01/01/2010'
              [data]     => 'A'
          )
)

My issue is I know I'll need usort and/or array_multisort(), but I'm not sure exactly sure how to efficiently iterate through a loop in order to sort with the criteria I gave.

我的问题是我知道我需要usort和/或array_multisort(),但我不确定如何有效地迭代循环以便按照我给出的标准进行排序。

2 个解决方案

#1


1  

Supposing your array in $data variable, try this:

假设你的数组在$ data变量中,试试这个:

<?php
$data = Array(
   0 => array (
            "category" => 'Value_1',
            "date"     => '01/01/2011',
            "data"     => 'A'
        ),
   1 => array (
            "category" => 'Value_3',
            "date"     => '01/01/2000',
            "data"     => 'B'
        ),
   2 => array (
            "category" => 'Value_2',
            "date"     => '01/01/2011',
            "data"     => 'D'
        ),
   3 => array (
            "category" => 'Value_2',
            "date"     => '01/01/2010',
            "data"     => 'A'
        ),
   4 => array (
              "category" => 'Value_2',
              "date"     => '01/01/2011',
              "data"     => 'C'
          )
);

$sorted = false;
foreach ($data as $index => $row) { $data[$index]['date'] = strtotime($data[$index]['date']); }
while (!$sorted) {
    $aux = null;
    $prevCat = null;
    $prevDate = null;
    $prevData = null;
    foreach ($data as $index => $row) {
        if ($prevCat != $row['category']) {
            $prevCat = $row['category'];
            $prevDate = $row['date'];
            $prevData = $row['data'];
            continue;
        } else {
            if ($row['date'] > $prevDate) {
                $sorted = false;
                $aux = $data[$index-1];
                $data[$index-1] = $row;
                $data[$index] = $aux;
                break;
            }
            if ($row['date'] == $prevDate && $row['data'] < $prevData) {
                $sorted = false;
                $aux = $data[$index-1];
                $data[$index-1] = $row;
                $data[$index] = $aux;
                break;
            }
            $prevCat = $row['category'];
            $prevDate = $row['date'];
            $prevData = $row['data'];
        }
    }
    $sorted = ($aux == null);
}
foreach ($data as $index => $row) $data[$index]['date'] = date("m/d/Y", $data[$index]['date']);
var_dump($data);

// outputs

//输出

array(5) {
  [0]=>
  array(3) {
    ["category"]=>
    string(7) "Value_1"
    ["date"]=>
    string(10) "01/01/2011                                                               
    ["data"]=>
    string(1) "A"
  }
  [1]=>
  array(3) {
    ["category"]=>
    string(7) "Value_3"
    ["date"]=>
    string(10) "01/01/2000"
    ["data"]=>
    string(1) "B"
  }
  [2]=>
  array(3) {
    ["category"]=>
    string(7) "Value_2"
    ["date"]=>
    string(10) "01/01/2011"
    ["data"]=>
    string(1) "C"
  }
  [3]=>
  array(3) {
    ["category"]=>
    string(7) "Value_2"
    ["date"]=>
    string(10) "01/01/2011"
    ["data"]=>
    string(1) "D"
  }
  [4]=>
  array(3) {
    ["category"]=>
    string(7) "Value_2"
    ["date"]=>
    string(10) "01/01/2010"
    ["data"]=>
    string(1) "A"
  }
}

#2


2  

Your problem can easily be solved with a nice comparison function and uasort() or usort(). Here is how it works:

使用一个很好的比较函数和uasort()或usort()可以很容易地解决你的问题。下面是它的工作原理:

Your comparison function accepts two parameters, which are elements of the array you sort. Return -1 if the first parameter should appear first in the sorted array, return 1 if the second parameter should appear first, and return 0 if both are considered equal in the sorting order.

您的比较函数接受两个参数,这些参数是您排序的数组的元素。如果第一个参数应该首先出现在排序数组中,则返回-1;如果第一个参数应该首先出现,则返回1;如果在排序顺序中认为两个参数都相等,则返回0。

Your order criteria is like: Sort by category. If category is the same, sort by date. If date is the same, sort by data.

您的订单标准如下:按类别排序。如果类别相同,则按日期排序。如果日期相同,则按数据排序。

Unfortunately your array is not properly structured. What if another category=Value_3 appears as the last element in the array. Should it be grouped with the other Value_3 entries, or should it be sorted alone? Depending on this answer, the array should be restructured for easier sorting.

不幸的是,您的阵列结构不正确。如果另一个category = Value_3作为数组中的最后一个元素出现,该怎么办?它应该与其他Value_3条目分组,还是应该单独排序?根据此答案,应重新构建阵列以便于排序。

Another improvement is the way the date is stored. America date format is completely unusable for sorting, neither as a string nor as a numeric value. Either transform it to a unix timestamp, or use ISO date format "YYYY-MM-DD". Both can easily be compared without further ado.

另一个改进是存储日期的方式。美国日期格式完全不能用于排序,既不能作为字符串也不能作为数值。将其转换为unix时间戳,或使用ISO日期格式“YYYY-MM-DD”。两者都可以轻松比较而不用多说。

#1


1  

Supposing your array in $data variable, try this:

假设你的数组在$ data变量中,试试这个:

<?php
$data = Array(
   0 => array (
            "category" => 'Value_1',
            "date"     => '01/01/2011',
            "data"     => 'A'
        ),
   1 => array (
            "category" => 'Value_3',
            "date"     => '01/01/2000',
            "data"     => 'B'
        ),
   2 => array (
            "category" => 'Value_2',
            "date"     => '01/01/2011',
            "data"     => 'D'
        ),
   3 => array (
            "category" => 'Value_2',
            "date"     => '01/01/2010',
            "data"     => 'A'
        ),
   4 => array (
              "category" => 'Value_2',
              "date"     => '01/01/2011',
              "data"     => 'C'
          )
);

$sorted = false;
foreach ($data as $index => $row) { $data[$index]['date'] = strtotime($data[$index]['date']); }
while (!$sorted) {
    $aux = null;
    $prevCat = null;
    $prevDate = null;
    $prevData = null;
    foreach ($data as $index => $row) {
        if ($prevCat != $row['category']) {
            $prevCat = $row['category'];
            $prevDate = $row['date'];
            $prevData = $row['data'];
            continue;
        } else {
            if ($row['date'] > $prevDate) {
                $sorted = false;
                $aux = $data[$index-1];
                $data[$index-1] = $row;
                $data[$index] = $aux;
                break;
            }
            if ($row['date'] == $prevDate && $row['data'] < $prevData) {
                $sorted = false;
                $aux = $data[$index-1];
                $data[$index-1] = $row;
                $data[$index] = $aux;
                break;
            }
            $prevCat = $row['category'];
            $prevDate = $row['date'];
            $prevData = $row['data'];
        }
    }
    $sorted = ($aux == null);
}
foreach ($data as $index => $row) $data[$index]['date'] = date("m/d/Y", $data[$index]['date']);
var_dump($data);

// outputs

//输出

array(5) {
  [0]=>
  array(3) {
    ["category"]=>
    string(7) "Value_1"
    ["date"]=>
    string(10) "01/01/2011                                                               
    ["data"]=>
    string(1) "A"
  }
  [1]=>
  array(3) {
    ["category"]=>
    string(7) "Value_3"
    ["date"]=>
    string(10) "01/01/2000"
    ["data"]=>
    string(1) "B"
  }
  [2]=>
  array(3) {
    ["category"]=>
    string(7) "Value_2"
    ["date"]=>
    string(10) "01/01/2011"
    ["data"]=>
    string(1) "C"
  }
  [3]=>
  array(3) {
    ["category"]=>
    string(7) "Value_2"
    ["date"]=>
    string(10) "01/01/2011"
    ["data"]=>
    string(1) "D"
  }
  [4]=>
  array(3) {
    ["category"]=>
    string(7) "Value_2"
    ["date"]=>
    string(10) "01/01/2010"
    ["data"]=>
    string(1) "A"
  }
}

#2


2  

Your problem can easily be solved with a nice comparison function and uasort() or usort(). Here is how it works:

使用一个很好的比较函数和uasort()或usort()可以很容易地解决你的问题。下面是它的工作原理:

Your comparison function accepts two parameters, which are elements of the array you sort. Return -1 if the first parameter should appear first in the sorted array, return 1 if the second parameter should appear first, and return 0 if both are considered equal in the sorting order.

您的比较函数接受两个参数,这些参数是您排序的数组的元素。如果第一个参数应该首先出现在排序数组中,则返回-1;如果第一个参数应该首先出现,则返回1;如果在排序顺序中认为两个参数都相等,则返回0。

Your order criteria is like: Sort by category. If category is the same, sort by date. If date is the same, sort by data.

您的订单标准如下:按类别排序。如果类别相同,则按日期排序。如果日期相同,则按数据排序。

Unfortunately your array is not properly structured. What if another category=Value_3 appears as the last element in the array. Should it be grouped with the other Value_3 entries, or should it be sorted alone? Depending on this answer, the array should be restructured for easier sorting.

不幸的是,您的阵列结构不正确。如果另一个category = Value_3作为数组中的最后一个元素出现,该怎么办?它应该与其他Value_3条目分组,还是应该单独排序?根据此答案,应重新构建阵列以便于排序。

Another improvement is the way the date is stored. America date format is completely unusable for sorting, neither as a string nor as a numeric value. Either transform it to a unix timestamp, or use ISO date format "YYYY-MM-DD". Both can easily be compared without further ado.

另一个改进是存储日期的方式。美国日期格式完全不能用于排序,既不能作为字符串也不能作为数值。将其转换为unix时间戳,或使用ISO日期格式“YYYY-MM-DD”。两者都可以轻松比较而不用多说。