【问题标题】:PHP grouping arrays within array by valuePHP按值对数组中的数组进行分组
【发布时间】:2013-02-19 17:36:39
【问题描述】:

您好,我遇到了一些问题,但我似乎找不到答案。我有一个包含数组的数组,并希望根据字段的相同值将这些子数组分组。这是我的代码,允许我根据值中的数组对数组进行排序。如何根据共享值对结果进行分组?我可能不知道所有的值,因为有些值是基于日期的,我想例如每天/每月分组

if($filter == "ORDER BY TODO_REF DESC"){
$type_sort = 0;
};
if($filter == "ORDER BY TODO_PRIO DESC"){
$type_sort = 2;
};
if($filter == "ORDER BY TODO_DEAD DESC"){
$type_sort = 3;
};

function aasort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
    $sorter[$ii]=$va[$key];
}
asort($sorter);
foreach ($sorter as $ii => $va) {
    $ret[$ii]=$array[$ii];
}
$array=$ret;
}

 aasort($test_array, $type_sort);
print_r($test_array);

当前输出:

priority
Array
 (

[3] => Array
    (
        [0] => 2
        [1] => sdfsdgdfgdfgdfg
        [2] => 3
        [3] => 2013-05-30 13:53:23
    )

[2] => Array
    (
        [0] => 1
        [1] => This must also be done
        [2] => 4
        [3] => 2013-03-28 12:13:34
    )

[1] => Array
    (
        [0] => 1
        [1] => testing this show me 2
        [2] => 5
        [3] => 2029-02-23 17:27:20
    )

[0] => Array
    (
        [0] => 1
        [1] => Do this task and make sure it gets done
        [2] => 5
        [3] => 2013-06-28 12:12:41
    )

)

我想要的是这样的,根据子数组键 2 将它们分成单独的数组:

Array
(
[3] => Array
    (
        [0] => 2
        [1] => sdfsdgdfgdfgdfg
        [2] => 3
        [3] => 2013-05-30 13:53:23
    )

)
Array
(
[2] => Array
    (
        [0] => 1
        [1] => This must also be done
        [2] => 4
        [3] => 2013-03-28 12:13:34
    )

)
Array
(
[1] => Array
    (
        [0] => 1
        [1] => testing this show me 2
        [2] => 5
        [3] => 2029-02-23 17:27:20
    )

[0] => Array
    (
        [0] => 1
        [1] => Do this task and make sure it gets done
        [2] => 5
        [3] => 2013-06-28 12:12:41
    )

)

【问题讨论】:

    标签: php arrays sorting grouping multidimensional-array


    【解决方案1】:
    $array_1 = array();
    $array_2 = array();
    foreach($test_array as $item) {
      if($item[0] == 1) {
        $array_1[] = $item;
      } elseif($item[0] == 2) {
        $array_2[] = $item;
      }
    }
    $final_array = array($array_1, $array_2);
    

    必须有更优化的代码,但这应该可以满足您的需求。

    【讨论】:

    • 所以我知道这会做 2 个数组。当我 print_r $test_array[0];我得到一个数组,但为什么该数组等于 1?另外,它的作用是将它放在两个数组中,但似乎没有在子数组值上这样做?此外,当我使用日期时,它需要动态添加更多数组,因为会有更多值分组。
    • 那么你必须使用自动生成的$array[$i] 而不是$array_1$array_2
    【解决方案2】:

    array_multisort() 是您所追求的,它将允许您按子数组对主数组进行排序并维护键值链接

    我使用下面的方法对一个相当庞大的多维数组进行排序,该数组基于具有许多列和可排序列的表上的排序顺序箭头 asc/desc。它有点乱,但你应该能够遵循它。

    if (strlen($_GET['col'])<1) {
                    foreach ($dataarray as $key => $row) {
                        $spend[$key]  = $row[6];
                    }
                    array_multisort($spend, SORT_DESC, $dataarray);
                } else if ($_GET['col']=="spend"){
                    foreach ($dataarray as $key => $row) {
                        $spend[$key]  = $row[3];
                    }
                    if ($_GET['order']=="asc") {
                        array_multisort($spend, SORT_ASC, $dataarray);
                    } else {
                        array_multisort($spend, SORT_DESC, $dataarray);
                    }
                } else if ($_GET['col']=="name"){
                    foreach ($dataarray as $key => $row) {
                        $name[$key]  = $row[1];
                    }
                    if ($_GET['order']=="asc") {
                        array_multisort($name, SORT_ASC, $dataarray);
                    } else {
                        array_multisort($name, SORT_DESC, $dataarray);
                    }
                } else if ($_GET['col']=="avg"){
                    foreach ($dataarray as $key => $row) {
                        $avg[$key]  = $row[4];
                    }
                    if ($_GET['order']=="asc") {
                        array_multisort($avg, SORT_ASC, $dataarray);
                    } else {
                        array_multisort($avg, SORT_DESC, $dataarray);
                    }
                } else if ($_GET['col']=="sites"){
                    foreach ($dataarray as $key => $row) {
                        $sites[$key]  = $row[5];
                    }
                    if ($_GET['order']=="asc") {
                        array_multisort($sites, SORT_ASC, $dataarray);
                    } else {
                        array_multisort($sites, SORT_DESC, $dataarray);
                    }
                } else if ($_GET['col']=="rate"){
                    foreach ($dataarray as $key => $row) {
                        $rate[$key]  = $row[6];
                    }
                    if ($_GET['order']=="asc") {
                        array_multisort($rate, SORT_ASC, $dataarray);
                    } else {
                        array_multisort($rate, SORT_DESC, $dataarray);
                    }
                } else {
                    foreach ($dataarray as $key => $row) {
                        $spend[$key]  = $row[2];
                    }
                    array_multisort($spend, SORT_DESC, $dataarray);
                }
    

    【讨论】:

      【解决方案3】:
      1. 而不是if-elseif-elseif-elseif...else 条件块来确定排序/分组列,我总是推荐一个查找数组,然后是一个非常快速的isset() 调用。我发现这种语法更简洁、更易读、更易于维护。
      2. 为了对分组数据进行正确排序,请提前对数据进行排序(当它仍处于其更简单的形式时)。 usort() 与宇宙飞船操作员 (php7) 将为您完成所有艰苦的工作。请务必使用use$groupsort 变量传递到函数范围内。
      3. 在迭代输入数组时,隔离标识列值(并根据需要准备),然后将其用作临时键来确定应存储$row 数据的组。
      4. 最后,使用array_values() 删除临时标识键(如果需要)。

      代码:(Demo)

      $filter = "ORDER BY TODO_PRIO DESC";
      $lookup = [
          "ORDER BY TODO_REF DESC" => 0,
          "ORDER BY TODO_PRIO DESC" => 2,
          "ORDER BY TODO_DEAD DESC" => 3
      ];
      $groupsort = isset($lookup[$filter]) ? $lookup[$filter] : 0;  
      
      $array = [
          [1, "Do this task and make sure it gets done", 5, "2013-06-28 12:12:41"],
          [1, "testing this show me 2", 5, "2029-02-23 17:27:20"],
          [1, "This must also be done", 4, "2013-03-28 12:13:34"],
          [2, "sdfsdgdfgdfgdfg", 3, "2013-05-30 13:53:23"],
          [2, "Another priority", 3, "2013-03-28 11:11:11"]
      ];
      
      // sort DESC on $groupsort column values
      usort($array, function($a, $b)use($groupsort) { return $b[$groupsort] <=> $a[$groupsort]; }); 
      
      // group by $groupsort column values
      foreach ($array as $row) {
          $id = $row[$groupsort];                             // just to improve readability
          if ($groupsort == 3) { $id = substr($id, 0, 10); }  // remove time from datetime stamp
          $result[$id][] = $row;                              // store the current value
      }
      
      var_export(array_values($result));                      // reindex first level (remove temp keys);
      

      输出:

      array (
        0 => 
        array (
          0 => 
          array (
            0 => 1,
            1 => 'Do this task and make sure it gets done',
            2 => 5,
            3 => '2013-06-28 12:12:41',
          ),
          1 => 
          array (
            0 => 1,
            1 => 'testing this show me 2',
            2 => 5,
            3 => '2029-02-23 17:27:20',
          ),
        ),
        1 => 
        array (
          0 => 
          array (
            0 => 1,
            1 => 'This must also be done',
            2 => 4,
            3 => '2013-03-28 12:13:34',
          ),
        ),
        2 => 
        array (
          0 => 
          array (
            0 => 2,
            1 => 'sdfsdgdfgdfgdfg',
            2 => 3,
            3 => '2013-05-30 13:53:23',
          ),
          1 => 
          array (
            0 => 2,
            1 => 'Another priority',
            2 => 3,
            3 => '2013-03-28 11:11:11',
          ),
        ),
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-11-26
        • 1970-01-01
        • 1970-01-01
        • 2016-10-10
        • 1970-01-01
        • 2012-12-16
        相关资源
        最近更新 更多