如何在PHP中按特定列对多维列数组进行排序



我在PHP文档中找到了函数"array_multisort",意思是对数组"列"进行排序。他们提供了一个示例,其中用户有一个行数组,然后用户必须将这个行数组转换为列数组。在我的例子中,数组已经由列设置,例如:

tablearray 
{
['Employee_ID'] = {0 => row1, 1 => row2, 2 => row3, 3 => row4}
['First_Name'] = {0 => row1, 1 => row2, 2 => row3, 3 => row4}
['LastName'] = {0 => row1, 1 => row2, 2 => row3, 3 =>row4}
 }

我想按Employee_ID排序,并且我需要所有其他列遵循相同的顺序。我试着:

   array_multisort($tablearray['Employee_ID'], SORT_ASC);

但是它只对第一列进行排序(这会变得很混乱)。该数组有10多个列,它根据搜索更改列名(列名是它的键)。在这个函数的PHP文档中,提供的示例显示,在将行数组转换为列数组之后,我们应该使用原始数组作为第三个参数来匹配键—我没有"原始"数组来进行匹配,因为我没有转换任何东西。

谢谢。


一个用户建议的期望输出:

Original:
array
{
['Employee_ID'] = (1002, 4508, 0002, 1112)
['Business_Unit'] = ('UER', 'ABC', 'XYZ', 'EER')
['LastName'] = ('Smith', 'Vicente', 'Simpson', 'Thompson')
}
Sorted by Employee ID:
array
{
['Employee_ID'] = (0002, 1002, 1112, 4508)
['Business_Unit'] = ('XYZ', 'UER', 'EER', 'ABC')
['LastName'] = ('Simpson','Smith', 'Thompson', 'Vicente')
}

——我的原始数组是一个数据库查询输出:

Array
 (
[0] => Array
    (
        [Employee_ID] => 0000
        [Supervisor_ID] => 00000
        [Location_Descr] => somewhere
        [Start_Date] => 06/03/2002
        [Service_Date] => 06/03/2002
        [Rehire_Date] => 00/00/00
        [Business_Unit] => YYYY
        [Job_Title] => Manager
        [Email] => email@example.com
        [Dept_Desc] => bla bla bla
        [Employee_Name_LF] => Last, First
        [Supervisor_Name_LF] => Last, First
        [Term_Date] => 00/00/00
        [Preferred_Name] => Someone
        [Source] => Sheet2
    )
)

还有几行。其主要目的是将结果显示为HTML表并生成CSV文件。我已经使用修改后的结构(我发布的第一个)制作了这些函数。我以为处理那种结构会更容易些……确实是这样,但不幸的是,不是为了排序。

array_multisort文档(http://php.net/manual/en/function.array-multisort.php)建议将每个列作为一个单独的数组分开。但是,正如您所看到的,我有几列(用户可以在执行查询之前选择要显示的多列或少列)。所以我不能把它们都列在语句中)。

我愿意改变一切,只是为了使代码更好地工作。

丑陋-如果你格式化输入表,会容易得多。

$arr = array(
  'Employee_ID' => array('1002', '4508', '0002', '1112'),
  'Business_Unit' => array('UER', 'ABC', 'XYZ', 'EER'),
  'LastName' => array('Smith', 'Vicente', 'Simpson', 'Thompson')
);
$employees = array();
foreach (range(0, sizeof($arr[current(array_keys($arr))]) - 1) as $k) {
  $emp = array();
  foreach ($arr as $col => $vals) {
    $emp[$col] = $arr[$col][$k];
  }
  $employees[] = $emp;
}
$sort = array();
foreach ($employees as $k => $v) {
  $sort[$k] = $v['Employee_ID'];
}
array_multisort($sort, SORT_ASC, $employees);
print_r($employees);

和放回原来的格式:

$arr_sorted = array();
foreach (array_keys($arr) as $col) {
  $arr_sorted[$col] = array();
  foreach ($employees as $emp) {
    $arr_sorted[$col][] = $emp[$col];
  }
}
print_r($arr_sorted);

感谢您在问题中发布额外的细节,因为它们确实有助于理解您的问题的意图。
现在,你没有告诉我们这个表应该是什么样子;如果您希望员工每行一个,或每列一个。知道这个很重要。通常每行只有一名员工,特别是要将其导出到CVS时。然而,我怀疑你想要的是后者。否则你就会用一种非常复杂的方式来处理这个问题。

点的情况:正常一行布局:

<?php
$db = new PDO();
// Defining the fields we need here, to avoid having too long a string for the query.
$fields = "e.employee_id, e.first_name, e.lastname, u.business_unit, s.email";
// Do the sorting in the database itself. Not only is this faster, but it
// is also a lot easier to sort it exactly as you'd like.
// Note that I don't use prepared statements here, as there is no user-input.
$query = <<<outSQL
SELECT {$Fields} FROM `unit` AS u
INNER JOIN `employee` AS e ON e.employee_id = u.unit_id
INNER JOIN `employee` AS s ON s.employee_id = u.supervisor_id
ORDER BY e.`employee_id`
outSQL;
$data = $db->query($query);
// Creating a printf() template for the output, to make the code easier to maintain.
$rowTemplate = <<<outHTML
        <tr>
            <td>%1$d</td>
            <td>%2$s</td>
            <td>%3$s</td>
        </tr>
outHTML;
// Generate the table template, using placeholders for where the data will be added..
$tableTemplate = <<<outHTML
<table>
    <thead>
        <tr>
            <th>ID</th>
            <th>First name</th>
            <th>Last name</th>
        </tr>
    </thead>
    <tbody>
%s
    </tbody>
</table>
outHTML;
// Regular table output, one employee per line.
$temp = '';
foreach ($data as $e) {
    // hs() is a shortcut function to htmlspecialchars (), to prevent against XSS.
    $temp .= sprintf($rowTemplate, $e['employee_id'], hs($e['first_name']), hs($e['lastname']));
}
// Add the rows to the table, so that you can echo the completed product wherever you need.
$employeeTable = sprintf($tableTemplate, $temp);

如果您想在每个列上执行一个操作,则会变得有点复杂。不过,还是比你第一次尝试要简单一些。:)
也就是像这样:

<?php
$db = new PDO();
// Defining the fields we need here, to avoid having too long a string for the query.
$fields = "employee_id, first_name, lastname";
// Do the sorting in the database itself. Not only is this faster, but it
// is also a lot easier to sort it exactly as you'd like.
// Note that I don't use prepared statements here, as there is no user-input.
$data = $db->query("SELECT {$Fields} FROM `employees` ORDER BY `employee_id`");
// We need to know how many columns we'll have. One per employee.
$columns = count ($data);
// Rows have a header in front of each line, and one td tag for each employee.
$rowTemplate = "tt<th>%s</th>n".str_repeat("ttt<td>%s</td>n", $columns);
// Generate the table template, using placeholders for where the data will be added..
$tableTemplate = <<<outHTML
<table>
    <tbody>
%s
    </tbody>
</table>
outHTML;
// Reformat the array to give us the data per-column.
$temp = array ();
foreach ($data as $field => $e) {
    // Since we've already sorted the data in the database we don't need to do any further sorting here.
    // Also note that I'm doing the escaping here, seeing as this array will only be used for output.
    $temp['Employee ID'][] = intval($e['employee_id']);
    $temp['First name'][] = hs($e['first_name']);
    $temp['Last name'][] = hs($e['lastname']);
}
// Now we do the same as in the above example.
$rows = '';
foreach ($temp as $label => $l) {
    // We have the label as the first template variable to be added, so put it as the first element.
    array_unshift($l, $label);
    // Add the current row of items to the output, using the previously established template.
    $rows = vprintf($rowTemplate, $l);
}
// Add the rows to the table, so that you can echo the completed product wherever you need.
$employeeTable = sprintf($tableTemplate, $temp);

PS:还没有测试代码,但它应该工作。

我遇到了他的问题,经过许多焦虑,在php手册页的注释中找到了一个非常好的解决方案-我现在有以下函数,每当我需要解决这类问题时,我都会使用它。

function fnArrayOrderby(){
//function to sort a database type array of rows by the values in one or more column
//source http://php.net/manual/en/function.array-multisort.php - user notes
//example of use -> $sorted = fnArrayOrderby($data, 'volume', SORT_DESC, 'edition', SORT_ASC);
$args = func_get_args(); //Gets an array of the function's argument list (which can vary in length)
//echo "sorting  ".$args[0]."<br>";
if (!isset($args[0])) { return;}
$data = array_shift($args); //Shift an element off the beginning of array
foreach ($args as $n => $field) {
if (is_string($field)) {
$tmp = array();
foreach ($data as $key => $row)
$tmp[$key] = $row[$field];
$args[$n] = $tmp;
}
}
$args[] = &$data;
call_user_func_array('array_multisort', $args);
return array_pop($args);
}

相关内容

  • 没有找到相关文章